home *** CD-ROM | disk | FTP | other *** search
/ Visual Cafe 3 / Visual Cafe 3.ISO / Vcafe / JFC.bin / JComponent.java < prev    next >
Text File  |  1998-06-30  |  109KB  |  3,185 lines

  1. /*
  2.  * @(#)JComponent.java    2.61 98/04/10
  3.  *
  4.  * Copyright (c) 1997 Sun Microsystems, Inc. All Rights Reserved.
  5.  *
  6.  * This software is the confidential and proprietary information of Sun
  7.  * Microsystems, Inc. ("Confidential Information").  You shall not
  8.  * disclose such Confidential Information and shall use it only in
  9.  * accordance with the terms of the license agreement you entered into
  10.  * with Sun.
  11.  *
  12.  * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
  13.  * SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  14.  * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
  15.  * PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES
  16.  * SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING
  17.  * THIS SOFTWARE OR ITS DERIVATIVES.
  18.  *
  19.  */
  20. package com.sun.java.swing;
  21.  
  22.  
  23. import java.awt.Component;
  24. import java.awt.Container;
  25. import java.awt.Color;
  26. import java.awt.Cursor;
  27. import java.awt.Window;
  28. import java.awt.Font;
  29. import java.awt.FontMetrics;
  30. import java.awt.Frame;
  31. import java.awt.Dimension;
  32. import java.awt.Insets;
  33. import java.awt.Graphics;
  34. import java.awt.Window;
  35. import java.awt.AWTEvent;
  36. import java.awt.Rectangle;
  37. import java.util.Hashtable;
  38. import java.util.Dictionary;
  39. import java.util.Enumeration;
  40. import java.util.Locale;
  41. import java.util.Vector;
  42. import java.awt.Point;
  43. import java.awt.Image;
  44. import java.awt.LayoutManager2;
  45. import java.awt.Color;
  46.  
  47. import java.awt.event.*;
  48. import java.beans.*;
  49.  
  50. import java.applet.Applet;
  51.  
  52. import java.io.Serializable;
  53. import java.io.ObjectOutputStream;
  54. import java.io.ObjectInputStream;
  55. import java.io.IOException;
  56.  
  57. import com.sun.java.swing.border.*;
  58. import com.sun.java.swing.event.*;
  59. import com.sun.java.swing.plaf.*;
  60. import com.sun.java.accessibility.*;
  61.  
  62.  
  63. /**
  64.  * The base class for the Swing components. JComponent provides:
  65.  * <ul>
  66.  * <li>A "pluggable look and feel" (l&f) that can be specified by the
  67.  *     programmer or (optionally) selected by the user at runtime.
  68.  * <li>Components that are designed to be combined and extended in order
  69.  *     to create custom components.
  70.  * <li>Comprehensive keystroke-handling that works with nested components.
  71.  * <li>Action objects, for single-point control of program actions initiated
  72.  *     by multiple components.
  73.  * <li>A border property that implicitly defines the component's insets.
  74.  * <li>The ability to set the preferred, minimim, and maximum size for a
  75.  *     component.
  76.  * <li>ToolTips -- short descriptions that pop up when the cursor lingers
  77.  *     over a component.
  78.  * <li>Autoscrolling -- automatic scrolling in a list, table, or tree that
  79.  *     occurs when the user is dragging the mouse.
  80.  * <li>Simple, easy dialog construction using static methods in the JOptionPane
  81.  *     class that let you display information and query the user.
  82.  * <li>Slow-motion graphics rendering using debugGraphics so you can see
  83.  *     what is being displayed on screen and whether or not it is being
  84.  *     overwritten.
  85.  * <li>Support for Accessibility.
  86.  * <li>Support for international Localization.
  87.  * </ul>
  88.  * For more information on these subjects, see the
  89.  * <a href="doc-files/package.html">Swing package description</a>
  90.  * <p>
  91.  * Warning: serialized objects of this class will not be compatible with
  92.  * future swing releases.  The current serialization support is appropriate
  93.  * for short term storage or RMI between Swing1.0 applications.  It will
  94.  * not be possible to load serialized Swing1.0 objects with future releases
  95.  * of Swing.  The JDK1.2 release of Swing will be the compatibility
  96.  * baseline for the serialized form of Swing objects.
  97.  *
  98.  * @see KeyStroke
  99.  * @see Action
  100.  * @see #setBorder
  101.  * @see #registerKeyboardAction
  102.  * @see JOptionPane
  103.  * @see #setDebugGraphicsOptions
  104.  * @see #setToolTipText
  105.  * @see #setAutoscrolls
  106.  *
  107.  * @version 2.61 04/10/98
  108.  * @author Hans Muller
  109.  * @author Arnaud Weber
  110.  */
  111. public abstract class JComponent extends Container implements Serializable
  112. {
  113.     /* The following fields support set methods for the corresponding
  114.      * java.awt.Component properties.
  115.      */
  116.  
  117.     private Dimension preferredSize;
  118.     private Dimension minimumSize;
  119.     private Dimension maximumSize;
  120.     private Float alignmentX;
  121.     private Float alignmentY;
  122.     private AncestorNotifier ancestorNotifier;
  123.     Rectangle _bounds = new Rectangle();
  124.  
  125.  
  126.     /* Backing store for JComponent properties and listeners
  127.      */
  128.  
  129.     protected ComponentUI ui;
  130.     protected EventListenerList listenerList = new EventListenerList();
  131.  
  132.     private Hashtable clientProperties;
  133.     private VetoableChangeSupport vetoableChangeSupport;
  134.     private Autoscroller autoscroller;
  135.     private int flags;
  136.     private Border border;
  137.  
  138.     private transient Rectangle tmpRect;
  139.  
  140.  
  141.     /**
  142.      * Constant used for registerKeyboardAction() which
  143.      * means that the command should be invoked when
  144.      * the component has the focus.
  145.      */
  146.     public static final int WHEN_FOCUSED = 0;
  147.  
  148.     /**
  149.      * Constant used for registerKeyboardAction() which
  150.      * means that the comand should be invoked when the receiving
  151.      * component is an ancestor of the focused component or is
  152.      * itself the focused component.
  153.      */
  154.     public static final int WHEN_ANCESTOR_OF_FOCUSED_COMPONENT = 1;
  155.  
  156.     /**
  157.      * Constant used for registerKeyboardAction() which
  158.      * means that the command should be invoked when
  159.      * the receiving component is in the window that has the focus
  160.      * or is itself the focused component.
  161.      */
  162.     public static final int WHEN_IN_FOCUSED_WINDOW = 2;
  163.  
  164.     /**
  165.      * Constant used by some of the apis to mean that no condition is defined.
  166.      */
  167.     public static final int UNDEFINED_CONDITION = -1;
  168.  
  169.     /**
  170.      * The key used by JComponent to access keyboard bindings.
  171.      */
  172.     private static final String KEYBOARD_BINDINGS_KEY = "_KeyboardBindings";
  173.  
  174.     /**
  175.      * The comment to display when the cursor is over the component,
  176.      * also known as a "value tip", "flyover help", or "flyover label".
  177.      */
  178.     public static final String TOOL_TIP_TEXT_KEY = "ToolTipText";
  179.  
  180.     private static final String NEXT_FOCUS = "nextFocus";
  181.  
  182.     /** Private flags **/
  183.     private static final int REQUEST_FOCUS_DISABLED = 0;
  184.     private static final int IS_DOUBLE_BUFFERED     = 1;
  185.     private static final int ANCESTOR_USING_BUFFER  = 2;
  186.     private static final int IS_PAINTING_TILE       = 3;
  187.     private static final int HAS_FOCUS              = 4;
  188.     private static final int IS_OPAQUE              = 5;
  189.  
  190.  
  191.     /**
  192.      * Default JComponent constructor.  This constructor does
  193.      * no initialization beyond calling the Container constructor,
  194.      * e.g. the initial layout manager is null.
  195.      */
  196.     public JComponent() {
  197.         super();
  198.         enableEvents(AWTEvent.FOCUS_EVENT_MASK);
  199.     }
  200.  
  201.  
  202.     /**
  203.      * Resets the UI property to a value from the current look and feel.
  204.      * JComponent subclasses must override this method like this:
  205.      * <pre>
  206.      *   public void updateUI() {
  207.      *      setUI((SliderUI)UIManager.getUI(this);
  208.      *   }
  209.      *  </pre>
  210.      *
  211.      * @see #setUI
  212.      * @see UIManager#getLookAndFeel
  213.      * @see UIManager#getUI
  214.      */
  215.     public void updateUI() {}
  216.  
  217.  
  218.     /**
  219.      * Set the look and feel delegate for this component.
  220.      * JComponent subclasses generally override this method
  221.      * to narrow the argument type, e.g. in JSlider:
  222.      * <pre>
  223.      * public void setUI(SliderUI newUI) {
  224.      *     super.setUI(newUI);
  225.      * }
  226.      *  </pre>
  227.      * <p>
  228.      * Additionaly JComponent subclasses must provide a getUI
  229.      * method that returns the correct type, e.g.
  230.      * <pre>
  231.      * public SliderUI getUI() {
  232.      *     return (SliderUI)ui;
  233.      * }
  234.      * </pre>
  235.      *
  236.      * @see #updateUI
  237.      * @see UIManager#getLookAndFeel
  238.      * @see UIManager#getUI
  239.      */
  240.     protected void setUI(ComponentUI newUI) {
  241.         /* We do not check that the UI instance is different
  242.          * before allowing the switch in order to enable the
  243.          * same UI instance *with different default settings*
  244.          * to be installed.
  245.          */
  246.         if (ui != null) {
  247.             ui.uninstallUI(this);
  248.         }
  249.         ComponentUI oldUI = ui;
  250.         ui = newUI;
  251.         if (ui != null) {
  252.             ui.installUI(this);
  253.         }
  254.         invalidate();
  255.         firePropertyChange("UI", oldUI, ui);
  256.     }
  257.  
  258.  
  259.     /**
  260.      * Return the UIDefaults key used to look up the name of the
  261.      * swing.plaf.ComponentUI class that defines the look and feel
  262.      * for this component.  Most applications will never need to
  263.      * call this method.  Subclasses of JComponent that support
  264.      * pluggable look and feel should override this method to
  265.      * return the name of the ComponentUI subclass that defines
  266.      * their look and feel.
  267.      *
  268.      * @return The name of a ComponentUI subclass.
  269.      * @see UIDefaults#getUI
  270.      * @beaninfo
  271.      *      expert: true
  272.      * description: UIClassID
  273.      */
  274.     public String getUIClassID() {
  275.         return "not a pluggable look and feel class";
  276.     }
  277.  
  278.  
  279.     /**
  280.      * Returns the graphics object used to paint this component.
  281.      * If DebugGraphics is turned on we create a new DebugGraphics
  282.      * object if neccessary otherwise we just configure the
  283.      * specified graphics objects foreground and font.
  284.      *
  285.      * @return A Graphics object configured for this component
  286.      */
  287.     protected Graphics getComponentGraphics(Graphics g) {
  288.         Graphics componentGraphics = g;
  289.         if (ui != null) {
  290.             if ((DebugGraphics.debugComponentCount() != 0) &&
  291.                     (shouldDebugGraphics() != 0) &&
  292.                     !(g instanceof DebugGraphics)) {
  293.                 if(g instanceof SwingGraphics) {
  294.                     if(!(((SwingGraphics)g).subGraphics() instanceof DebugGraphics)) {
  295.                         componentGraphics = new DebugGraphics(((SwingGraphics)g).subGraphics(),this);
  296.                         componentGraphics = SwingGraphics.createSwingGraphics(componentGraphics);
  297.                     }
  298.                 } else {
  299.                     componentGraphics = new DebugGraphics(g,this);
  300.                 }
  301.             }
  302.         }
  303.         componentGraphics.setColor(getForeground());
  304.         componentGraphics.setFont(getFont());
  305.  
  306.         return componentGraphics;
  307.     }
  308.  
  309.  
  310.     /**
  311.      * If the UI delegate is non-null, call its paint
  312.      * method.  We pass the delegate a copy of the Graphics
  313.      * object to protect the rest of the paint code from
  314.      * irrevocable changes (e.g. Graphics.translate()).
  315.      *
  316.      * @see #paint
  317.      */
  318.     protected void paintComponent(Graphics g) {
  319.         if (ui != null) {
  320.             Graphics scratchGraphics = SwingGraphics.createSwingGraphics(g.create());
  321.             try {
  322.                 ui.update(scratchGraphics, this);
  323.             }
  324.             finally {
  325.                 scratchGraphics.dispose();
  326.             }
  327.         }
  328.     }
  329.  
  330.     /**
  331.      * Paint this component's children.
  332.      * If shouldUseBuffer is true, no component ancestor has a buffer and
  333.      * the component children can use a buffer if they have one.
  334.      * Otherwise, one ancestor has a buffer currently in use and children
  335.      * should not use a buffer to paint.
  336.      * @see #paint
  337.      * @see java.awt.Container#paint
  338.      */
  339.     protected void paintChildren(Graphics g) {
  340.         boolean isJComponent;
  341.         boolean shouldRecycle = false;
  342.         SwingGraphics sg;
  343.  
  344.         if(g instanceof SwingGraphics) {
  345.             sg = (SwingGraphics)g;
  346.         } else {
  347.             sg = SwingGraphics.createSwingGraphics(g);
  348.             shouldRecycle = true;
  349.         }
  350.  
  351.         synchronized(getTreeLock()) {
  352.             for (int i = getComponentCount() - 1 ; i >= 0 ; i--) {
  353.                 Component comp = getComponent(i);
  354.                 if (comp != null && isLightweightComponent(comp) && (comp.isVisible() == true)) {
  355.                     Rectangle cr;
  356.                     isJComponent = (comp instanceof JComponent);
  357.  
  358.                     if(isJComponent) {
  359.                         if(tmpRect == null) {
  360.                             tmpRect = new Rectangle();
  361.                         }
  362.                         cr = tmpRect;
  363.                         ((JComponent)comp).getBounds(cr);
  364.                     } else {
  365.                         cr = comp.getBounds();
  366.                     }
  367.  
  368.                     if (sg.isClipIntersecting(cr)) {
  369.                         Graphics cg = SwingGraphics.createGraphics(
  370.                             g, cr.x, cr.y, cr.width, cr.height);
  371.                         boolean shouldSetFlagBack = false;
  372.                         try {
  373.                             if(isJComponent) {
  374.                                 if(getFlag(ANCESTOR_USING_BUFFER)) {
  375.                                     ((JComponent)comp).setFlag(ANCESTOR_USING_BUFFER,true);
  376.                                     shouldSetFlagBack = true;
  377.                                 }
  378.                                 if(getFlag(IS_PAINTING_TILE)) {
  379.                                     ((JComponent)comp).setFlag(IS_PAINTING_TILE,true);
  380.                                     shouldSetFlagBack = true;
  381.                                 }
  382.                                 ((JComponent)comp).paint(cg);
  383.                             } else {
  384.                                 comp.paint(cg);
  385.                             }
  386.                         } finally {
  387.                             cg.dispose();
  388.                             if(shouldSetFlagBack) {
  389.                                 ((JComponent)comp).setFlag(ANCESTOR_USING_BUFFER,false);
  390.                                 ((JComponent)comp).setFlag(IS_PAINTING_TILE,false);
  391.                             }
  392.                         }
  393.                     }
  394.                 }
  395.  
  396.             }
  397.         }
  398.         if(shouldRecycle) {
  399.             sg.recycle();
  400.         }
  401.     }
  402.  
  403.     /**
  404.      * Paint the component's border.
  405.      *
  406.      * @see #paint
  407.      * @see #setBorder
  408.      */
  409.     protected void paintBorder(Graphics g) {
  410.         Border border = getBorder();
  411.         if (border != null) {
  412.             border.paintBorder(this, g, 0, 0, getWidth(), getHeight());
  413.         }
  414.     }
  415.  
  416.  
  417.     /**
  418.      * Calls paint(g).  Doesn't clear the background but see
  419.      * ComponentUI.update() which is called by paintComponent.
  420.      *
  421.      * @see #paint
  422.      * @see #paintComponent
  423.      * @see com.sun.java.swing.plaf.ComponentUI
  424.      */
  425.     public void update(Graphics g) {
  426.         paint(g);
  427.     }
  428.  
  429.  
  430.  
  431.  
  432.     /**
  433.      * This method is invoked by Swing to draw components.
  434.      * Applications should not invoke paint directly,
  435.      * but should instead use the <code>repaint</code> method to
  436.      * schedule the component for redrawing.
  437.      * <p>
  438.      * This method actually delegates the work of painting to three
  439.      * protected methods: <code>paintComponent</code>, <code>paintBorder</code>,
  440.      * and <code>paintChildren</code>.  They're called in the order
  441.      * listed to ensure that children appear on top of component itself.
  442.      * Generally speaking, the component and its children should not
  443.      * paint in the insets area allocated to the border. Subclasses can
  444.      * just override this method, as always.  A subclass that just
  445.      * wants to specialize the UI (look and feel) delegates paint
  446.      * method should just override <code>paintComponent</code>.
  447.      *
  448.      * @see #paintComponent
  449.      * @see #paintBorder
  450.      * @see #paintChildren
  451.      * @see #getComponentGraphics
  452.      * @see #repaint
  453.      */
  454.     public void paint(Graphics g) {
  455.     boolean shouldClearPaintFlags = false;
  456.  
  457.         if (getWidth() == 0 || getHeight() == 0) {
  458.             return;
  459.         }
  460.         Graphics componentGraphics = getComponentGraphics(g);
  461.         boolean shouldRecycle;
  462.         if((componentGraphics instanceof SwingGraphics)) {
  463.             shouldRecycle = false;
  464.         } else {
  465.             shouldRecycle = true;
  466.         }
  467.         SwingGraphics co = SwingGraphics.createSwingGraphics(componentGraphics);
  468.         Image offscr = null;
  469.         RepaintManager repaintManager = RepaintManager.currentManager(this);
  470.         int clipX = co.getClipX();
  471.         int clipY = co.getClipY();
  472.         int clipW = co.getClipWidth();
  473.         int clipH = co.getClipHeight();
  474.  
  475.         if(clipW > getWidth()) {
  476.             clipW = getWidth();
  477.         }
  478.         if(clipH > getHeight()) {
  479.             clipH = getHeight();
  480.         }
  481.  
  482.     if(getParent() != null && !(getParent() instanceof JComponent)) {
  483.         adjustPaintFlags();
  484.         shouldClearPaintFlags = true;
  485.     }
  486.  
  487.         if(repaintManager.isDoubleBufferingEnabled() &&
  488.            !getFlag(ANCESTOR_USING_BUFFER) && isDoubleBuffered()) {
  489.             int bw,bh;
  490.             int x,y,maxx,maxy;
  491.             offscr = repaintManager.getOffscreenBuffer(this,clipW,clipH);
  492.  
  493.             if(shouldRecycle) {
  494.                 co.recycle();
  495.                 shouldRecycle = false;
  496.             }
  497.             co = SwingGraphics.createSwingGraphics(offscr.getGraphics());
  498.             co.translate(-clipX,-clipY);
  499.  
  500.             bw = offscr.getWidth(null);
  501.             bh = offscr.getHeight(null);
  502.  
  503.             if(bw > clipW) {
  504.                 bw = clipW;
  505.             }
  506.             if(bh > clipH) {
  507.                 bh = clipH;
  508.             }
  509.             try {
  510.                 setFlag(ANCESTOR_USING_BUFFER,true);
  511.                 setFlag(IS_PAINTING_TILE,true);
  512.                 for(x = 0, maxx = clipW; x < maxx ;  x += bw ) {
  513.                     for(y=0, maxy = clipH; y < maxy ; y += bh) {
  514.                         if((y+bh) >= maxy && (x+bw) >= maxx)
  515.                             setFlag(IS_PAINTING_TILE,false);
  516.                         co.translate(-x,-y);
  517.                         co.setClip(clipX+x,clipY + y,bw,bh);
  518.                         if(!rectangleIsObscured(clipX,clipY,bw,bh)) {
  519.                             paintComponent(co);
  520.                             paintBorder(co);
  521.                         }
  522.                         paintChildren(co);
  523.                         g.drawImage(offscr,clipX + x,clipY + y,this);
  524.                         co.translate(x,y);
  525.                     }
  526.                 }
  527.             } finally {
  528.                 setFlag(ANCESTOR_USING_BUFFER,false);
  529.                 setFlag(IS_PAINTING_TILE,false);
  530.                 co.dispose();
  531.             }
  532.         } else {
  533.             if (!rectangleIsObscured(clipX,clipY,clipW,clipH)) {
  534.                 paintComponent(co);
  535.                 paintBorder(co);
  536.             }
  537.             paintChildren(co);
  538.         }
  539.         if(shouldRecycle) {
  540.             co.recycle();
  541.         }
  542.     if(shouldClearPaintFlags) {
  543.         setFlag(ANCESTOR_USING_BUFFER,false);
  544.         setFlag(IS_PAINTING_TILE,false);
  545.     }
  546.     }
  547.     
  548.     private void adjustPaintFlags() {
  549.     JComponent jparent = null;
  550.     Container parent;
  551.     for(parent = getParent() ; parent != null ; parent =
  552.         parent.getParent()) {
  553.         if(parent instanceof JComponent) {
  554.         jparent = (JComponent) parent;
  555.         if(jparent.getFlag(ANCESTOR_USING_BUFFER))
  556.           setFlag(ANCESTOR_USING_BUFFER, true);
  557.         if(jparent.getFlag(IS_PAINTING_TILE))
  558.           setFlag(IS_PAINTING_TILE, true);
  559.         break;
  560.         }
  561.     }
  562.     }
  563.     
  564.  
  565.     /**
  566.      *  Returns true if the receiving component is currently painting a tile.
  567.      *  If this method returns true, paint will be called again for another
  568.      *  tile. This method returns false if you are not painting a tile or
  569.      *  if the last tile is painted.
  570.      *  Use this method to keep some state you might need between tiles.
  571.      */
  572.     public boolean isPaintingTile() {
  573.         return getFlag(IS_PAINTING_TILE);
  574.     }
  575.  
  576.  
  577.     /**
  578.      * Override this method and return true if your component is the root of
  579.      * of a component tree with its own focus cycle.
  580.      */
  581.     public boolean isFocusCycleRoot() {
  582.         return false;
  583.     }
  584.  
  585.     /**
  586.      * Override this method and return true if your JComponent manages focus.
  587.      * If your component manages focus, the focus manager will handle your
  588.      * component's children. All key event will be sent to your key listener
  589.      * including TAB and SHIFT+TAB. CONTROL + TAB and CONTROL + SHIFT + TAB
  590.      * will move the focus to the next / previous component.
  591.      */
  592.     public boolean isManagingFocus() {
  593.         return false;
  594.     }
  595.  
  596.     /**
  597.      * Specifies the next component to get the focus after this one,
  598.      * for example, when the tab key is pressed. Invoke this method
  599.      * to override the default focus-change sequence.
  600.      * @beaninfo
  601.      *      expert: true
  602.      * description: The next component to get focus after this one.
  603.      */
  604.     public void setNextFocusableComponent(Component aComponent) {
  605.         putClientProperty(NEXT_FOCUS,aComponent);
  606.     }
  607.  
  608.     /**
  609.      * Return the next focusable component or null if the focus manager
  610.      * should choose the next focusable component automatically
  611.      */
  612.     public Component getNextFocusableComponent() {
  613.         return (Component) getClientProperty(NEXT_FOCUS);
  614.     }
  615.  
  616.     /**
  617.      *  Set whether the receiving component can obtain the focus by
  618.      *  calling requestFocus. The default value is true.
  619.      *  Note: Setting this property to false will not prevent the focus
  620.      *  manager from setting the focus to this component, it will prevent
  621.      *  the component from getting the focus when the focus is requested
  622.      *  explicitly. Override isFocusTraversable and return false if the
  623.      *  component should never get the focus.
  624.      * @beaninfo
  625.      *      expert: true
  626.      * description: Whether the component can obtain the focus by calling requestFocus.
  627.      */
  628.     public void setRequestFocusEnabled(boolean aFlag) {
  629.         setFlag(REQUEST_FOCUS_DISABLED,(aFlag ? false:true));
  630.     }
  631.  
  632.     /** Return whether the receiving component can obtain the focus by
  633.      *  calling requestFocus
  634.      *  @see #setRequestFocusEnabled()
  635.      */
  636.     public boolean isRequestFocusEnabled() {
  637.         return (getFlag(REQUEST_FOCUS_DISABLED) ? false : true);
  638.     }
  639.  
  640.     /** Set focus on the receiving component if isRequestFocusEnabled returns true **/
  641.     public void requestFocus() {
  642.         if(isRequestFocusEnabled()) {
  643.             super.requestFocus();
  644.         }
  645.     }
  646.  
  647.     /** Set the focus on the receiving component. This method is for focus managers, you
  648.      *  rarely want to call this method, use requestFocus() enstead.
  649.      */
  650.     public void grabFocus() {
  651.         super.requestFocus();
  652.     }
  653.  
  654.     /**
  655.      * Set the preferred size of the receiving component.
  656.      * if <code>preferredSize</code> is null, the UI will
  657.      * be asked for the preferred size
  658.      * @beaninfo
  659.      *   preferred: true
  660.      * description: The preferred size of the component.
  661.      */
  662.     public void setPreferredSize(Dimension preferredSize) {
  663.         this.preferredSize = preferredSize;
  664.     }
  665.  
  666.     /**
  667.      * If the preferredSize has been set to a non-null value
  668.      * just return it.  If the UI delegates getPreferredSize()
  669.      * method returns a non null then value return that, otherwise
  670.      * defer to the components layout manager.
  671.      *
  672.      * @return the value of the preferredSize property.
  673.      * @see #setPreferredSize
  674.      */
  675.     public Dimension getPreferredSize() {
  676.         if (preferredSize != null) {
  677.             return preferredSize;
  678.         }
  679.         Dimension size = null;
  680.         if (ui != null) {
  681.             size = ui.getPreferredSize(this);
  682.         }
  683.         return (size != null) ? size : super.getPreferredSize();
  684.     }
  685.  
  686.  
  687.     /**
  688.      * Sets the maximumSize of this component to a constant
  689.      * value.  Subsequent calls to getMaximumSize will always
  690.      * return this value, the components UI will not be asked
  691.      * to compute it.  Setting the maximumSize to null
  692.      * restores the default behavior.
  693.      *
  694.      * @see #getMaximumSize
  695.      * @beaninfo
  696.      *   preferred: true
  697.      * description: The maximum size of the component.
  698.      */
  699.     public void setMaximumSize(Dimension maximumSize) {
  700.         this.maximumSize = maximumSize;
  701.     }
  702.  
  703.     /**
  704.      * If the maximumSize has been set to a non-null value
  705.      * just return it.  If the UI delegates getMaximumSize()
  706.      * method returns a non null value then return that, otherwise
  707.      * defer to the components layout manager.
  708.      *
  709.      * @return the value of the maximumSize property.
  710.      * @see #setMaximumSize
  711.      */
  712.     public Dimension getMaximumSize() {
  713.         if (maximumSize != null) {
  714.             return maximumSize;
  715.         }
  716.         Dimension size = null;
  717.         if (ui != null) {
  718.             size = ui.getMaximumSize(this);
  719.         }
  720.         return (size != null) ? size : super.getMaximumSize();
  721.     }
  722.  
  723.  
  724.     /**
  725.      * Sets the minimumSize of this component to a constant
  726.      * value.  Subsequent calls to getMinimumSize will always
  727.      * return this value, the components UI will not be asked
  728.      * to compute it.  Setting the minimumSize to null
  729.      * restores the default behavior.
  730.      *
  731.      * @see #getMinimumSize
  732.      * @beaninfo
  733.      *   preferred: true
  734.      * description: The minimum size of the component.
  735.      */
  736.     public void setMinimumSize(Dimension minimumSize) {
  737.         this.minimumSize = minimumSize;
  738.     }
  739.  
  740.     /**
  741.      * If the minimumSize has been set to a non-null value
  742.      * just return it.  If the UI delegates getMinimumSize()
  743.      * method returns a non null value then return that, otherwise
  744.      * defer to the components layout manager.
  745.      *
  746.      * @return the value of the minimumSize property.
  747.      * @see #setMinimumSize
  748.      */
  749.     public Dimension getMinimumSize() {
  750.         if (minimumSize != null) {
  751.             return minimumSize;
  752.         }
  753.         Dimension size = null;
  754.         if (ui != null) {
  755.             size = ui.getMinimumSize(this);
  756.         }
  757.         return (size != null) ? size : super.getMinimumSize();
  758.     }
  759.  
  760.  
  761.     /**
  762.      * Give the UI delegate an opportunity to define the precise
  763.      * shape of this component for the sake of mouse processing.
  764.      *
  765.      * @return true if this component logically contains x,y.
  766.      * @see java.awt.Component#contains(int, int)
  767.      */
  768.     public boolean contains(int x, int y) {
  769.         return (ui != null) ? ui.contains(this, x, y) : super.contains(x, y);
  770.     }
  771.  
  772.  
  773.     /**
  774.      * Sets the border of this component.  The Border object is
  775.      * responsible for defining the insets for the component
  776.      * (overriding any insets set directly on the component) and
  777.      * for optionally rendering any border decorations within the
  778.      * bounds of those insets.  Borders should be used (rather
  779.      * than insets) for creating both decorative and non-decorative
  780.      * (e.g. margins and padding) regions for a swing component.
  781.      * Compound borders can be used to nest multiple borders within a
  782.      * single component.
  783.      * <p>
  784.      * This is a bound property.
  785.      *
  786.      * @param border the border to be rendered for this component
  787.      * @see Border
  788.      * @see CompoundBorder
  789.      * @beaninfo
  790.      *       bound: true
  791.      *   preferred: true
  792.      * description: The component's border.
  793.      */
  794.     public void setBorder(Border border) {
  795.         Border         oldBorder = this.border;
  796.  
  797.         this.border = border;
  798.         firePropertyChange("border", oldBorder, border);
  799.         invalidate();
  800.     }
  801.  
  802.     /**
  803.      * Returns the border of this component or null if no border is
  804.      * currently set.
  805.      *
  806.      * @return the border object for this component
  807.      * @see setBorder
  808.      */
  809.     public Border getBorder() {
  810.         return border;
  811.     }
  812.  
  813.     /**
  814.      * If a border has been set on this component, returns the
  815.      * border's insets, else calls super.getInsets.
  816.      *
  817.      * @return the value of the insets property.
  818.      * @see #setBorder
  819.      */
  820.     public Insets getInsets() {
  821.         if (border != null) {
  822.             return border.getBorderInsets(this);
  823.         }
  824.         return super.getInsets();
  825.     }
  826.  
  827.  
  828.     /**
  829.      * @return the value of the alignmentY property.
  830.      * @see #setAlignmentY
  831.      * @see java.awt.Component#getAlignmentY
  832.      */
  833.     public float getAlignmentY() {
  834.         return (alignmentY != null) ? alignmentY.floatValue() : super.getAlignmentY();
  835.     }
  836.  
  837.     /**
  838.      * Set the value of the alignmentY property.
  839.      * @see #getAlignmentY
  840.      * @beaninfo
  841.      *   preferred: true
  842.      * description: The preferred vertical alignment of the component
  843.      */
  844.     public void setAlignmentY(float alignmentY) {
  845.         this.alignmentY = new Float(alignmentY > 1.0f ? 1.0f : alignmentY < 0.0f ? 0.0f : alignmentY);
  846.     }
  847.  
  848.  
  849.     /**
  850.      * @return the value of the alignmentX property.
  851.      * @see #setAlignmentX
  852.      * @see java.awt.Component#getAlignmentX
  853.      */
  854.     public float getAlignmentX() {
  855.         return (alignmentX != null) ? alignmentX.floatValue() : super.getAlignmentX();
  856.     }
  857.  
  858.     /**
  859.      * Set the value of the alignmentX property.
  860.      * @see #getAlignmentX
  861.      * @beaninfo
  862.      *   preferred: true
  863.      * description: The preferred horizontal alignment of the component
  864.      */
  865.     public void setAlignmentX(float alignmentX) {
  866.         this.alignmentX = new Float(alignmentX > 1.0f ? 1.0f : alignmentX < 0.0f ? 0.0f : alignmentX);
  867.     }
  868.  
  869.     /**
  870.      * Returns this component's graphics context, which lets you draw
  871.      * on a component. Use this method get a Graphics object and
  872.      * then invoke oeprations on that object to draw on the component.
  873.      */
  874.     public Graphics getGraphics() {
  875.         if (shouldDebugGraphics() != 0) {
  876.             DebugGraphics graphics = new DebugGraphics(super.getGraphics(),
  877.                                                        this);
  878.             return graphics;
  879.         }
  880.         return SwingGraphics.createSwingGraphics(super.getGraphics());
  881.     }
  882.  
  883.  
  884.     /** Enables or disables diagnostic information about every graphics
  885.       * operation performed within the component or one of its children. The
  886.       * value of <b>debugOptions</b> determines how the component should
  887.       * display this information:
  888.       * <ul>
  889.       * <li>DebugGraphics.LOG_OPTION - causes a text message to be printed.
  890.       * <li>DebugGraphics.FLASH_OPTION - causes the drawing to flash several
  891.       * times.
  892.       * <li>DebugGraphics.BUFFERED_OPTION - creates an ExternalWindow that
  893.       * displays the operations performed on the View's offscreen buffer.
  894.       * </ul>
  895.       * <b>debug</b> is bitwise OR'd into the current value.
  896.       * DebugGraphics.NONE_OPTION disables debugging.
  897.       * A value of 0 causes no changes to the debugging options.
  898.       * @beaninfo
  899.       *   preferred: true
  900.       * description: Diagnostic options for graphics operations.
  901.       */
  902.     public void setDebugGraphicsOptions(int debugOptions) {
  903.         DebugGraphics.setDebugOptions(this, debugOptions);
  904.     }
  905.  
  906.     /** Returns the state of graphics debugging.
  907.       * @see #setDebugGraphicsOptions
  908.       */
  909.     public int getDebugGraphicsOptions() {
  910.         return DebugGraphics.getDebugOptions(this);
  911.     }
  912.  
  913.     /**
  914.      * Returns <b>true</b> if debug information is enabled for this JComponent
  915.      * or one if its parents.
  916.      */
  917.     int shouldDebugGraphics() {
  918.         return DebugGraphics.shouldComponentDebug(this);
  919.     }
  920.  
  921.     /**
  922.      * Register a new keyboard action.
  923.      * <b>anAction</b> will be invoked if a key event matching <b>aKeyStroke</b> occurs
  924.      * and <b>aCondition</b> is verified. The KeyStroke object defines a
  925.      * particular combination of a keyboard key and one or more modifiers
  926.      * (alt, shift, ctrl, meta).
  927.      * <p>
  928.      * The <b>aCommand</b> will be set in the delivered event if specified.
  929.      * <p>
  930.      * The Condition can be one of:
  931.      * <blockquote>
  932.      * <DL>
  933.      * <DT>WHEN_FOCUSED
  934.      * <DD>The action will be invoked only when the keystroke occurs
  935.      *     while the component has the focus.
  936.      * <DT>WHEN_IN_FOCUSED_WINDOW
  937.      * <DD>The action will be invoked when the keystroke occurs while
  938.      *     the component has the focus or if the component is in the
  939.      *     window that has the focus. Note that the component need not
  940.      *     be an immediate descendent of the window -- it can be
  941.      *     anywhere in the window's containment hierarchy. In other
  942.      *     words, whenever <em>any</em> component in the window has the focus,
  943.      *     the action registered with this component is invoked.
  944.      * <DT>WHEN_ANCESTOR_OF_FOCUSED_COMPONENT
  945.      * <DD>The action will be invoked when the keystroke occurs while the
  946.      *     component has the focus or if the component is an ancestor of
  947.      *     the component that has the focus.
  948.      * </DL>
  949.      * </blockquote>
  950.      * <p>
  951.      * The combination of keystrokes and conditions lets you define high
  952.      * level (semantic) action events for a specified keystroke+modifier
  953.      * combination (using the KeyStroke class) and direct to a parent or
  954.      * child of a component that has the focus, or to the component itself.
  955.      * In other words, in any hierarchical structure of components, an
  956.      * arbitrary key-combination can be immediately directed to the
  957.      * appropriate component in the hierarchy, and cause a specific method
  958.      * to be invoked (usually by way of adapter objects).
  959.      * <p>
  960.      * If an action has already been registered for the receiving
  961.      * container, with the same charCode and the same modifiers,
  962.      * <b>anAction</b> will replace the action.
  963.      *
  964.      * @see KeyStroke
  965.      */
  966.     public void registerKeyboardAction(ActionListener anAction,String aCommand,KeyStroke aKeyStroke,int aCondition) {
  967.       Hashtable bindings;
  968.       boolean firstKeyboardAction = false;
  969.  
  970.       synchronized(this) {
  971.         bindings = (Hashtable) getClientProperty(KEYBOARD_BINDINGS_KEY);
  972.         if(bindings == null) {
  973.           bindings = new Hashtable();
  974.           putClientProperty(KEYBOARD_BINDINGS_KEY,bindings);
  975.           firstKeyboardAction = true;
  976.         }
  977.       }
  978.  
  979.       synchronized(bindings) {
  980.         bindings.put(aKeyStroke,new KeyboardBinding(anAction,aCommand,aKeyStroke,aCondition));
  981.       }
  982.  
  983.       /* This is the first time a keyboard binding is added, let's order
  984.        * keyboard events...
  985.        * ALERT: we need to enable events. Adding a listener will not work since
  986.        *        we want our listener to be after all other listeners.
  987.        */
  988.       if(firstKeyboardAction) {
  989.         enableEvents(AWTEvent.KEY_EVENT_MASK);
  990.       }
  991.     }
  992.  
  993.     /**
  994.      *  Calls registerKeyboardAction(ActionListener,String,KeyStroke,condition) with a null command.
  995.      */
  996.     public void registerKeyboardAction(ActionListener anAction,KeyStroke aKeyStroke,int aCondition) {
  997.         registerKeyboardAction(anAction,null,aKeyStroke,aCondition);
  998.     }
  999.  
  1000.     private Hashtable keyboardBindings() {
  1001.         Hashtable bindings;
  1002.         synchronized(this) {
  1003.             bindings = (Hashtable) getClientProperty(KEYBOARD_BINDINGS_KEY);
  1004.         }
  1005.         return bindings;
  1006.     }
  1007.  
  1008.     /**
  1009.      * Unregister a keyboard action.
  1010.      *
  1011.      * @see #registerKeyboardAction
  1012.      */
  1013.     public void unregisterKeyboardAction(KeyStroke aKeyStroke) {
  1014.         Hashtable bindings = keyboardBindings();
  1015.  
  1016.         if(bindings == null)
  1017.             return;
  1018.         synchronized(bindings) {
  1019.             bindings.remove(aKeyStroke);
  1020.         }
  1021.  
  1022.         if(bindings.size() == 0) {
  1023.             /** ALERT. We need a way to disable keyboard events only if there is no
  1024.              *        keyboard listener.
  1025.              */
  1026.         }
  1027.     }
  1028.  
  1029.     /**
  1030.      * Return the KeyStrokes that will initiate registered actions.
  1031.      *
  1032.      * @return an array of KeyStroke objects
  1033.      * @see #registerKeyboardAction
  1034.      */
  1035.     public KeyStroke[] getRegisteredKeyStrokes() {
  1036.         Hashtable bindings = keyboardBindings();
  1037.         KeyStroke result[];
  1038.         int i;
  1039.         Enumeration keys;
  1040.  
  1041.         if(bindings == null)
  1042.             return new KeyStroke[0];
  1043.         synchronized(bindings) {
  1044.             result = new KeyStroke[bindings.size()];
  1045.             i = 0;
  1046.             keys = bindings.keys();
  1047.             while(keys.hasMoreElements())
  1048.                 result[i++] = (KeyStroke) keys.nextElement();
  1049.         }
  1050.         return result;
  1051.     }
  1052.  
  1053.     /**
  1054.      * Return the condition that determines whether a registered action
  1055.      * occurs in response to the specified keystroke.
  1056.      *
  1057.      * @return the action-keystroke condition
  1058.      * @see #registerKeyboardAction
  1059.      */
  1060.     public int getConditionForKeyStroke(KeyStroke aKeyStroke) {
  1061.         Hashtable bindings = keyboardBindings();
  1062.         if(bindings == null)
  1063.             return UNDEFINED_CONDITION;
  1064.         synchronized(bindings) {
  1065.             KeyboardBinding kb = (KeyboardBinding) bindings.get(aKeyStroke);
  1066.             if(kb != null) {
  1067.                 return kb.getCondition();
  1068.             }
  1069.         }
  1070.         return UNDEFINED_CONDITION;
  1071.     }
  1072.  
  1073.     /**
  1074.      * Return the object that will perform the action registered for a
  1075.      * given keystroke.
  1076.      *
  1077.      * @return the ActionListener object invoked when the keystroke occurs
  1078.      * @see #registerKeyboardAction
  1079.      */
  1080.     public ActionListener getActionForKeyStroke(KeyStroke aKeyStroke) {
  1081.         Hashtable bindings = keyboardBindings();
  1082.  
  1083.         if(bindings == null)
  1084.             return null;
  1085.         synchronized(bindings) {
  1086.             KeyboardBinding kb = (KeyboardBinding) bindings.get(aKeyStroke);
  1087.             if(kb != null) {
  1088.                 return kb.getAction();
  1089.             }
  1090.         }
  1091.         return null;
  1092.     }
  1093.  
  1094.  
  1095.  
  1096.     /**
  1097.      * Unregister all keyboard actions
  1098.      *
  1099.      * @see #registerKeyboardAction
  1100.      */
  1101.     public void resetKeyboardActions() {
  1102.       synchronized(this) {
  1103.           Hashtable bindings = (Hashtable) getClientProperty(KEYBOARD_BINDINGS_KEY);
  1104.           if(bindings != null) {
  1105.               bindings.clear();
  1106.           }
  1107.       }
  1108.       /* ALERT. We need a way to disable keyboard events only if there is no
  1109.        *        keyboard listener.
  1110.        */
  1111.     }
  1112.  
  1113.     /**
  1114.      * Request the focus for the component that should have the focus
  1115.      * by default. The default implementation will recursively request
  1116.      * the focus on the first component that is focus-traversable.
  1117.      *
  1118.      * @return false if the focus has not been set, otherwise
  1119.      *         return true
  1120.      */
  1121.     public boolean requestDefaultFocus() {
  1122.         Component ca[] = getComponents();
  1123.         int i;
  1124.         for(i=0 ; i < ca.length ; i++) {
  1125.             if(ca[i].isFocusTraversable()) {
  1126.                 if(ca[i] instanceof JComponent) {
  1127.                     ((JComponent)ca[i]).grabFocus();
  1128.                 } else {
  1129.                     ca[i].requestFocus();
  1130.                 }
  1131.                 return true;
  1132.             }
  1133.             if(ca[i] instanceof JComponent && !((JComponent)ca[i]).isManagingFocus()) {
  1134.                 if(((JComponent)(ca[i])).requestDefaultFocus()) {
  1135.                     return true;
  1136.                 }
  1137.             }
  1138.         }
  1139.         return false;
  1140.     }
  1141.  
  1142.     public void setVisible(boolean aFlag) {
  1143.         if(aFlag != isVisible()) {
  1144.             super.setVisible(aFlag);
  1145.             Container parent = getParent();
  1146.             if(parent != null) {
  1147.                 Rectangle r = getBounds();
  1148.                 parent.repaint(r.x,r.y,r.width,r.height);
  1149.             }
  1150.         }
  1151.     }
  1152.  
  1153.     /**
  1154.      * Identifies whether or not this component can receive the focus.
  1155.      * A disabled button, for example, would return false.
  1156.      *
  1157.      * @return true if this component can receive the focus
  1158.      */
  1159.     public boolean isFocusTraversable() {
  1160.       boolean result = false;
  1161.       Hashtable bindings;
  1162.  
  1163.       synchronized(this) {
  1164.         bindings = (Hashtable) getClientProperty(KEYBOARD_BINDINGS_KEY);
  1165.       }
  1166.       if(bindings != null) {
  1167.         synchronized(bindings) {
  1168.             Enumeration keys = bindings.keys();
  1169.             KeyboardBinding b;
  1170.  
  1171.             while(keys.hasMoreElements()) {
  1172.                 b = (KeyboardBinding) bindings.get(keys.nextElement());
  1173.                 if(b.getCondition() == WHEN_FOCUSED) {
  1174.                     result = true;
  1175.                     break;
  1176.                 }
  1177.             }
  1178.         }
  1179.       }
  1180.       return result;
  1181.     }
  1182.  
  1183.     protected void processFocusEvent(FocusEvent e) {
  1184.         switch(e.getID()) {
  1185.           case FocusEvent.FOCUS_GAINED:
  1186.               setFlag(HAS_FOCUS, true);
  1187.               break;
  1188.           case FocusEvent.FOCUS_LOST:
  1189.               setFlag(HAS_FOCUS, false);
  1190.               break;
  1191.         }
  1192.  
  1193.         // Call super *after* setting flag, in case listener calls paint.
  1194.         super.processFocusEvent(e);
  1195.     }
  1196.  
  1197.     /**
  1198.      * Process any key events that the component itself
  1199.      * recognizes.  This will be called after the focus
  1200.      * manager and any interested listeners have been
  1201.      * given a chance to steal away the event.  This
  1202.      * method will only be called is the event has not
  1203.      * yet been consumed.  This method is called prior
  1204.      * to the keyboard UI logic.
  1205.      * <p>
  1206.      * This is implemented to do nothing.  Subclasses would
  1207.      * normally override this method if they process some
  1208.      * key events themselves.  If the event is processed,
  1209.      * it should be consumed.
  1210.      */
  1211.     protected void processComponentKeyEvent(KeyEvent e) {
  1212.     }
  1213.  
  1214.     /** Override processKeyEvent to process events **/
  1215.     protected void processKeyEvent(KeyEvent e) {
  1216.       // focus manager gets to steal the event if it wants it.
  1217.       boolean result;
  1218.       boolean shouldProcessKey = false;
  1219.       if(FocusManager.isFocusManagerEnabled()) {
  1220.           FocusManager focusManager = FocusManager.getCurrentManager();
  1221.           focusManager.processKeyEvent(this,e);
  1222.           if(e.isConsumed()) {
  1223.               return;
  1224.           }
  1225.       }
  1226.  
  1227.       // This gives the key event listeners a crack at the event
  1228.       super.processKeyEvent(e);
  1229.  
  1230.       // give the component itself a crack at the event
  1231.       if (! e.isConsumed()) {
  1232.           processComponentKeyEvent(e);
  1233.       }
  1234.  
  1235.       if(e.getID() == KeyEvent.KEY_PRESSED) {
  1236.           shouldProcessKey = true;
  1237.           if(!KeyboardState.keyIsPressed(e.getKeyCode()))
  1238.               KeyboardState.registerKeyPressed(e.getKeyCode());
  1239.       } else if(e.getID() == KeyEvent.KEY_RELEASED) {
  1240.           if(KeyboardState.keyIsPressed(e.getKeyCode())) {
  1241.               shouldProcessKey = true;
  1242.               KeyboardState.registerKeyReleased(e.getKeyCode());
  1243.           }
  1244.       } else if(e.getID() == KeyEvent.KEY_TYPED) {
  1245.           shouldProcessKey = true;
  1246.       }
  1247.  
  1248.       if(e.isConsumed()) {
  1249.         return;
  1250.       }
  1251.  
  1252.       if(shouldProcessKey && e.getID() == KeyEvent.KEY_PRESSED) {
  1253.         result = processKeyBindings(e,true);
  1254.         if(result)
  1255.           e.consume();
  1256.       } else if(shouldProcessKey && e.getID() == KeyEvent.KEY_RELEASED) {
  1257.           result = processKeyBindings(e,false);
  1258.           if(result) {
  1259.               e.consume();
  1260.           }
  1261.       } else if(shouldProcessKey && e.getID() == KeyEvent.KEY_TYPED) {
  1262.           result = processKeyBindings(e,false);
  1263.           if(result) {
  1264.               e.consume();
  1265.           }
  1266.       }
  1267.     }
  1268.  
  1269.     KeyboardBinding bindingForKeyStroke(KeyStroke ks,int condition) {
  1270.         Hashtable bindings;
  1271.         KeyboardBinding b;
  1272.         KeyboardBinding result = null;
  1273.  
  1274.         // synchronized(this) {
  1275.             bindings = (Hashtable) getClientProperty(KEYBOARD_BINDINGS_KEY);
  1276.         // }
  1277.         if(bindings != null) {
  1278.             // synchronized(bindings) {
  1279.                 b = (KeyboardBinding) bindings.get(ks);
  1280.                 // System.out.println("Bindings are " + bindings);
  1281.                 if(b != null) {
  1282.                     ActionListener action = b.getAction();
  1283.                     if((action instanceof Action) && !(((Action)action).isEnabled()))
  1284.                         action = null;
  1285.                     if(action != null) {
  1286.                         switch(b.getCondition()) {
  1287.                         case WHEN_FOCUSED:
  1288.                             if(condition == WHEN_FOCUSED)
  1289.                                 result = b;
  1290.                             break;
  1291.                         case WHEN_ANCESTOR_OF_FOCUSED_COMPONENT:
  1292.                             if(condition == WHEN_FOCUSED ||
  1293.                                condition == WHEN_ANCESTOR_OF_FOCUSED_COMPONENT)
  1294.                                 result = b;
  1295.                             break;
  1296.                         case WHEN_IN_FOCUSED_WINDOW:
  1297.                             if(condition == WHEN_FOCUSED ||
  1298.                                condition == WHEN_IN_FOCUSED_WINDOW ||
  1299.                                condition == WHEN_ANCESTOR_OF_FOCUSED_COMPONENT)
  1300.                                 result = b;
  1301.                             break;
  1302.                         }
  1303.                     }
  1304.                 }
  1305.             // }
  1306.         }
  1307.         return result;
  1308.     }
  1309.  
  1310.     boolean processKeyBinding(KeyEvent e,int condition,boolean pressed) {
  1311.         Hashtable bindings;
  1312.         int i,c;
  1313.         boolean onKeyRelease = (pressed?false:true);
  1314.         KeyboardBinding binding = null;
  1315.         KeyStroke ks;
  1316.  
  1317.         if(isEnabled()) {
  1318.             if(e.getID() == KeyEvent.KEY_TYPED) {
  1319.                 binding = bindingForKeyStroke((ks=KeyStroke.getKeyStroke(e.getKeyChar())),condition);
  1320.             } else {
  1321.                 binding = bindingForKeyStroke((ks=KeyStroke.getKeyStroke(e.getKeyCode(),e.getModifiers(),
  1322.                                                                      onKeyRelease)), condition);
  1323.             }
  1324.             //System.out.println("e=" + e + "ks is " + ks);
  1325.             if(binding != null) {
  1326.                 ActionListener listener = binding.getAction();
  1327.                 if(listener != null) {
  1328.                     listener.actionPerformed(new ActionEvent(this,ActionEvent.ACTION_PERFORMED,binding.getCommand()));
  1329.                     return true;
  1330.                 }
  1331.             }
  1332.         }
  1333.  
  1334.         return false;
  1335.     }
  1336.  
  1337.     boolean processKeyBindings(KeyEvent e,boolean pressed) {
  1338.       Container parent;
  1339.       Vector    processedComponents = new Vector();
  1340.  
  1341.       /* Do we have a key binding for e? */
  1342.       if(processKeyBinding(e,WHEN_FOCUSED,pressed))
  1343.         return true;
  1344.  
  1345.       processedComponents.addElement(this);
  1346.  
  1347.       /* We have no key binding. Let's try the path from our parent to the window excluded
  1348.        * We store the path components so we can avoid asking the same component twice.
  1349.        */
  1350.       parent = this.getParent();
  1351.       while(parent != null && !(parent instanceof Window) && !(parent instanceof Applet)) {
  1352.       if(parent instanceof JComponent) {
  1353.           if(((JComponent)parent).processKeyBinding(e,WHEN_ANCESTOR_OF_FOCUSED_COMPONENT,pressed))
  1354.         return true;
  1355.           processedComponents.addElement(parent);
  1356.       }
  1357.       parent = parent.getParent();
  1358.       }
  1359.  
  1360.       /* No components between the focused component and the window is actually interested
  1361.        * by the key event. Let's try the other JComponent in this window.
  1362.        */
  1363.       if(parent != null) {
  1364.         return JComponent.processKeyBindingsForAllComponents(e,parent,processedComponents,pressed);
  1365.       }
  1366.       return false;
  1367.     }
  1368.  
  1369.     static boolean processKeyBindingsForAllComponents(KeyEvent e,Container container,Vector alreadyProcessed,
  1370.                                                       boolean pressed) {
  1371.       int i;
  1372.       Component subComponents[];
  1373.  
  1374.       if(!container.isVisible() || !container.isEnabled()) {
  1375.       return false;
  1376.       }
  1377.  
  1378.       if(container instanceof JComponent && !alreadyProcessed.contains(container)) {
  1379.         if(((JComponent)container).processKeyBinding(e,WHEN_IN_FOCUSED_WINDOW,pressed))
  1380.           return true;
  1381.       }
  1382.  
  1383.       subComponents = container.getComponents();
  1384.       for(i=0 ; i < subComponents.length ; i++) {
  1385.       if(subComponents[i].isVisible() && subComponents[i].isEnabled()) {
  1386.           if(subComponents[i] instanceof Container) {
  1387.           if(processKeyBindingsForAllComponents(e,(Container)subComponents[i],alreadyProcessed,pressed))
  1388.             return true;
  1389.           }
  1390.       }
  1391.       }
  1392.       return false;
  1393.     }
  1394.  
  1395.     /**
  1396.      * Registers the text to display in a tool tip.
  1397.      * The text displays when the cursor lingers over the component.
  1398.      * <p>
  1399.      * See <a href="http://java.sun.com/docs/books/tutorial/ui/swing/tooltip.html">How to Use Tool Tips</a>
  1400.      * in <a href="http://java.sun.com/Series/Tutorial/index.html"><em>The Java Tutorial</em></a>
  1401.      * for further documentation.
  1402.      *
  1403.      * @param text  The string to display. If the text is null,
  1404.      *              the tool tip is turned off for this component.
  1405.      * @see #TOOL_TIP_TEXT_KEY
  1406.      * @beaninfo
  1407.      *   preferred: true
  1408.      * description: The text to display in a tool tip.
  1409.      */
  1410.     public void setToolTipText(String text) {
  1411.         putClientProperty(TOOL_TIP_TEXT_KEY, text);
  1412.         ToolTipManager toolTipManager = ToolTipManager.sharedInstance();
  1413.         if (text != null) {
  1414.             toolTipManager.registerComponent(this);
  1415.         } else {
  1416.             toolTipManager.unregisterComponent(this);
  1417.         }
  1418.     }
  1419.  
  1420.     /**
  1421.      * Return the tooltip string that has been set with setToolTipText()
  1422.      *
  1423.      * @return the text of the tool tip
  1424.      * @see #TOOL_TIP_TEXT_KEY
  1425.      */
  1426.     public String getToolTipText() {
  1427.         return (String)getClientProperty(TOOL_TIP_TEXT_KEY);
  1428.     }
  1429.  
  1430.  
  1431.     /**
  1432.      * Returns the string to be used as the tooltip for <i>event</i>.  By default
  1433.      * this returns any string set using setToolTipText().  If a component provides
  1434.      * more extensize API to support differing tooltips at different locations,
  1435.      * this method should be overridden.
  1436.      */
  1437.     public String getToolTipText(MouseEvent event) {
  1438.         return getToolTipText();
  1439.     }
  1440.  
  1441.     /**
  1442.      * Return the tooltip location in the receiving component coordinate system
  1443.      * If null is returned, Swing will choose a location.
  1444.      * The default implementation returns null.
  1445.      *
  1446.      * @param event  the MouseEvent that caused the ToolTipManager to
  1447.      *               show the tooltip.
  1448.      */
  1449.     public Point getToolTipLocation(MouseEvent event) {
  1450.         return null;
  1451.     }
  1452.  
  1453.  
  1454.     /**
  1455.      * Returns the instance of JToolTip that should be used to display the tooltip.
  1456.      * Components typically would not override this method, but it can be used to
  1457.      * cause different tooltips to be displayed differently.
  1458.      */
  1459.     public JToolTip createToolTip() {
  1460.         JToolTip tip = new JToolTip();
  1461.         tip.setComponent(this);
  1462.         return tip;
  1463.     }
  1464.  
  1465.     /**
  1466.      * Forwards the <b>scrollRectToVisible()</b> message to the JComponent's
  1467.      * parent. Components that can service the request, such as a JViewport,
  1468.      * override this method and perform the scrolling.
  1469.      *
  1470.      * @see JViewport
  1471.      */
  1472.     public void scrollRectToVisible(Rectangle aRect) {
  1473.         Container parent;
  1474.         int dx = getX(), dy = getY();
  1475.  
  1476.         for (parent = getParent();
  1477.                  !(parent == null) &&
  1478.                  !(parent instanceof JComponent) &&
  1479.                  !(parent instanceof CellRendererPane);
  1480.              parent = parent.getParent()) {
  1481.              Rectangle bounds = parent.getBounds();
  1482.  
  1483.              dx += bounds.x;
  1484.              dy += bounds.y;
  1485.         }
  1486.  
  1487.         if (!(parent == null) && !(parent instanceof CellRendererPane)) {
  1488.             aRect.x += dx;
  1489.             aRect.y += dy;
  1490.             ((JComponent)parent).scrollRectToVisible(aRect);
  1491.             aRect.x -= dx;
  1492.             aRect.y -= dy;
  1493.         }
  1494.     }
  1495.  
  1496.     /**
  1497.      * If <i>true</i> this component will automatically scroll its contents when
  1498.      * dragged, if contained in a component that supports scrolling, such as
  1499.      * JViewport
  1500.      *
  1501.      * @see JViewport
  1502.      * @see #getAutoscrolls
  1503.      *
  1504.      * @beaninfo
  1505.      *      expert: true
  1506.      * description: Whether this component automatically scrolls its contents when dragged.
  1507.      */
  1508.     public void setAutoscrolls(boolean autoscrolls) {
  1509.         if (autoscrolls) {
  1510.             if (autoscroller == null) {
  1511.                 autoscroller = new Autoscroller(this);
  1512.             }
  1513.         } else {
  1514.             if (autoscroller != null) {
  1515.                 autoscroller.stop();
  1516.                 autoscroller = null;
  1517.             }
  1518.         }
  1519.     }
  1520.  
  1521.     /**
  1522.      * Returns <i>true</i> if this component automatically scrolls its
  1523.      * contents when dragged, (when contained in a component that supports
  1524.      * scrolling, like JViewport
  1525.      *
  1526.      * @see JViewport
  1527.      * @see #setAutoscrolls
  1528.      */
  1529.     public boolean getAutoscrolls() {
  1530.         return autoscroller != null;
  1531.     }
  1532.  
  1533.     protected void processMouseMotionEvent(MouseEvent e) {
  1534.         boolean dispatch = true;
  1535.         if (autoscroller != null) {
  1536.             if (e.getID() == MouseEvent.MOUSE_DRAGGED) {
  1537.                 // We don't want to do the drags when the mouse moves if we're
  1538.                 // autoscrolling.  It makes it feel spastic.
  1539.                 dispatch = !autoscroller.timer.isRunning();
  1540.                 autoscroller.mouseDragged(e);
  1541.             }
  1542.         }
  1543.         if (dispatch) {
  1544.             super.processMouseMotionEvent(e);
  1545.         }
  1546.     }
  1547.  
  1548.     // Inner classes can't get at this method from a super class
  1549.     void superProcessMouseMotionEvent(MouseEvent e) {
  1550.         super.processMouseMotionEvent(e);
  1551.     }
  1552.  
  1553.     static class KeyboardBinding implements Serializable {
  1554.         ActionListener   action;
  1555.         String           command;
  1556.         KeyStroke keyStroke;
  1557.         int        condition;
  1558.  
  1559.         KeyboardBinding(ActionListener action,String aCommand,KeyStroke aKeyStroke,int condition) {
  1560.             this.action     = action;
  1561.             this.command    = aCommand;
  1562.             this.keyStroke  = aKeyStroke;
  1563.             this.condition  = condition;
  1564.         }
  1565.  
  1566.         ActionListener getAction() {
  1567.             return action;
  1568.         }
  1569.  
  1570.         String getCommand() {
  1571.             return command;
  1572.         }
  1573.  
  1574.         KeyStroke getKeyStroke() {
  1575.             return keyStroke;
  1576.         }
  1577.  
  1578.         int getCondition() {
  1579.             return condition;
  1580.         }
  1581.  
  1582.         public String toString() {
  1583.             return "KeyBinding ("+action+","+keyStroke+","+condition+")";
  1584.         }
  1585.     }
  1586.  
  1587.     // This class is used by the KeyboardState class to provide a single
  1588.     // instance which can be stored in the AppContext.
  1589.     static final class IntVector {
  1590.         int array[] = null;
  1591.         int count = 0;
  1592.         int capacity = 0;
  1593.  
  1594.         int size() {
  1595.             return count;
  1596.         }
  1597.  
  1598.         int elementAt(int index) {
  1599.             return array[index];
  1600.         }
  1601.  
  1602.         void addElement(int value) {
  1603.             if (count == capacity) {
  1604.                 capacity = (capacity + 2) * 2;
  1605.                 int[] newarray = new int[capacity];
  1606.                 if (count > 0) {
  1607.                     System.arraycopy(array, 0, newarray, 0, count);
  1608.                 }
  1609.                 array = newarray;
  1610.             }
  1611.             array[count++] = value;
  1612.         }
  1613.  
  1614.         void setElementAt(int value, int index) {
  1615.             array[index] = value;
  1616.         }
  1617.     }
  1618.  
  1619.     static class KeyboardState implements Serializable {
  1620.         private static final Object keyCodesKey =
  1621.             JComponent.KeyboardState.class;
  1622.  
  1623.         // Get the array of key codes from the AppContext.
  1624.         static IntVector getKeyCodeArray() {
  1625.             IntVector iv =
  1626.                 (IntVector)SwingUtilities.appContextGet(keyCodesKey);
  1627.             if (iv == null) {
  1628.                 iv = new IntVector();
  1629.                 SwingUtilities.appContextPut(keyCodesKey, iv);
  1630.             }
  1631.             return iv;
  1632.         }
  1633.  
  1634.         static void registerKeyPressed(int keyCode) {
  1635.             IntVector kca = getKeyCodeArray();
  1636.             int count = kca.size();
  1637.             int i;
  1638.             for(i=0;i<count;i++) {
  1639.                 if(kca.elementAt(i) == -1){
  1640.                     kca.setElementAt(keyCode, i);
  1641.                     return;
  1642.                 }
  1643.             }
  1644.             kca.addElement(keyCode);
  1645.         }
  1646.  
  1647.         static void registerKeyReleased(int keyCode) {
  1648.             IntVector kca = getKeyCodeArray();
  1649.             int count = kca.size();
  1650.             int i;
  1651.             for(i=0;i<count;i++) {
  1652.                 if(kca.elementAt(i) == keyCode) {
  1653.                     kca.setElementAt(-1, i);
  1654.                     return;
  1655.                 }
  1656.             }
  1657.         }
  1658.  
  1659.         static boolean keyIsPressed(int keyCode) {
  1660.             IntVector kca = getKeyCodeArray();
  1661.             int count = kca.size();
  1662.             int i;
  1663.             for(i=0;i<count;i++) {
  1664.                 if(kca.elementAt(i) == keyCode) {
  1665.                     return true;
  1666.                 }
  1667.             }
  1668.             return false;
  1669.         }
  1670.     }
  1671.  
  1672.  
  1673.     /**
  1674.      * --- Accessibility Support ---
  1675.      *
  1676.      *  JComponent will contain all of the methods in interface Accessible,
  1677.      *  though it won't actally implement the interface - that will be up
  1678.      *  to the individual objects which extend JComponent.
  1679.      */
  1680.  
  1681.     protected AccessibleContext accessibleContext = null;
  1682.  
  1683.     /**
  1684.      * Get the AccessibleContext associated with this JComponent
  1685.      *
  1686.      * @return the AccessibleContext of this JComponent
  1687.      */
  1688.     public AccessibleContext getAccessibleContext() {
  1689.         return accessibleContext;
  1690.     }
  1691.  
  1692.     /**
  1693.      * Inner class of JComponent used to provide default support for
  1694.      * accessibility.  This class is not meant to be used directly by
  1695.      * application developers, but is instead meant only to be
  1696.      * subclassed by component developers.  Due to a restriction that
  1697.      * protected inner classes cannot be subclassed outside of a
  1698.      * package, this inner class has been made public.  When this
  1699.      * restriction is lifted for JDK1.1.6, this class will be made
  1700.      * protected.
  1701.      * The class used to obtain the accessible role for this object.
  1702.      * <p>
  1703.      * Warning: serialized objects of this class will not be compatible with
  1704.      * future swing releases.  The current serialization support is appropriate
  1705.      * for short term storage or RMI between Swing1.0 applications.  It will
  1706.      * not be possible to load serialized Swing1.0 objects with future releases
  1707.      * of Swing.  The JDK1.2 release of Swing will be the compatibility
  1708.      * baseline for the serialized form of Swing objects.
  1709.      */
  1710.     public abstract class AccessibleJComponent extends AccessibleContext
  1711.         implements Serializable, AccessibleComponent {
  1712.  
  1713.         // AccessibleContext methods
  1714.         //
  1715.         /**
  1716.          * Get the accessible name of this object.  This should almost never
  1717.          * return java.awt.Component.getName(), as that generally isn't
  1718.          * a localized name, and doesn't have meaning for the user.  If the
  1719.          * object is fundamentally a text object (e.g. a menu item), the
  1720.          * accessible name should be the text of the object (e.g. "save").
  1721.          * If the object has a tooltip, the tooltip text may also be an
  1722.          * appropriate String to return.
  1723.          *
  1724.          * @return the localized name of the object -- can be null if this
  1725.          *         object does not have a name
  1726.          * @see AccessibleContext#setAccessibleName
  1727.          */
  1728.         public String getAccessibleName() {
  1729.             if (accessibleName != null) {
  1730.                 return accessibleName;
  1731.             } else {
  1732.                 Border border = getBorder();
  1733.                 if ((border != null) &&
  1734.                     (border instanceof TitledBorder)) {
  1735.                     return ((TitledBorder) border).getTitle();
  1736.                 }
  1737.             }
  1738.             return null;
  1739.         }
  1740.  
  1741.         /**
  1742.          * Get the accessible description of this object.  This should be
  1743.          * a concise, localized description of what this object is - what
  1744.          * is it's meaning to the user.  If the object has a tooltip, the
  1745.          * tooltip text may be an appropriate string to return, assuming
  1746.          * it contains a concise description of the object (instead of just
  1747.          * the name of the object - e.g. a "Save" icon on a toolbar that
  1748.          * had "save" as the tooltip text shouldn't return the tooltip
  1749.          * text as the description, but something like "Saves the current
  1750.          * text document" instead).
  1751.          *
  1752.          * @return the localized description of the object -- can be null if
  1753.          * this object does not have a description
  1754.          * @see AccessibleContext#setAccessibleDescription
  1755.          */
  1756.         public String getAccessibleDescription() {
  1757.             if (accessibleDescription != null) {
  1758.                 return accessibleDescription;
  1759.             } else {
  1760.                 try {
  1761.                     String ttt = getToolTipText(null);
  1762.                     if (ttt != null) {
  1763.                         return ttt;
  1764.                     }
  1765.                 } catch (Exception e) {
  1766.                     // Just in case the subclass overrode the
  1767.                     // getToolTipText method and actually
  1768.                     // requires a MouseEvent.
  1769.                     // [[[FIXME:  WDW - we probably should require this
  1770.                     // method to take a MouseEvent and just pass it on
  1771.                     // to getToolTipText.  The swing-feedback traffic
  1772.                     // leads me to believe getToolTipText might change,
  1773.                     // though, so I was hesitant to make this change at
  1774.                     // this time.]]]
  1775.                 }
  1776.             }
  1777.             return null;
  1778.         }
  1779.  
  1780.         /**
  1781.          * Get the role of this object.
  1782.          *
  1783.          * @return an instance of AccessibleRole describing the role of the
  1784.          * object
  1785.          * @see AccessibleRole
  1786.          */
  1787.         public AccessibleRole getAccessibleRole() {
  1788.             return AccessibleRole.SWING_COMPONENT;
  1789.         }
  1790.  
  1791.         /**
  1792.          * Get the state of this object.
  1793.          *
  1794.          * @return an instance of AccessibleStateSet containing the current
  1795.          * state set of the object
  1796.          * @see AccessibleState
  1797.          */
  1798.         public AccessibleStateSet getAccessibleStateSet() {
  1799.             return SwingUtilities.getAccessibleStateSet(JComponent.this);
  1800.         }
  1801.  
  1802.         /**
  1803.          * Get the Accessible parent of this object.  If the parent of this
  1804.          * object implements Accessible, this method should simply return
  1805.          * getParent().
  1806.          *
  1807.          * @return the Accessible parent of this object -- can be null if this
  1808.          * object does not have an Accessible parent
  1809.          */
  1810.         public Accessible getAccessibleParent() {
  1811.             if (accessibleParent != null) {
  1812.                 return accessibleParent;
  1813.             } else {
  1814.                 Container parent = getParent();
  1815.                 if (parent instanceof Accessible) {
  1816.                     return (Accessible) parent;
  1817.                 }
  1818.             }
  1819.             return null;
  1820.         }
  1821.  
  1822.         /**
  1823.          * Get the index of this object in its accessible parent.
  1824.          *
  1825.          * @return the index of this object in its parent; -1 if this
  1826.          * object does not have an accessible parent.
  1827.          * @see #getAccessibleParent
  1828.          */
  1829.         public int getAccessibleIndexInParent() {
  1830.             return SwingUtilities.getAccessibleIndexInParent(JComponent.this);
  1831.         }
  1832.  
  1833.         /**
  1834.          * Returns the number of accessible children in the object.  If all
  1835.          * of the children of this object implement Accessible, than this
  1836.          * method should return the number of children of this object.
  1837.          *
  1838.          * @return the number of accessible children in the object.
  1839.          */
  1840.         public int getAccessibleChildrenCount() {
  1841.             return SwingUtilities.getAccessibleChildrenCount(JComponent.this);
  1842.         }
  1843.  
  1844.         /**
  1845.          * Return the nth Accessible child of the object.
  1846.          *
  1847.          * @param i zero-based index of child
  1848.          * @return the nth Accessible child of the object
  1849.          */
  1850.         public Accessible getAccessibleChild(int i) {
  1851.             return SwingUtilities.getAccessibleChild(JComponent.this,i);
  1852.         }
  1853.  
  1854.  
  1855.         /**
  1856.          * Return the locale of this object.
  1857.          *
  1858.          * @return the locale of this object
  1859.          */
  1860.         public Locale getLocale() {
  1861.             return JComponent.this.getLocale();
  1862.         }
  1863.  
  1864.         /**
  1865.          * Get the AccessibleComponent associated with this object if one
  1866.          * exists.  Otherwise return null.
  1867.          */
  1868.         public AccessibleComponent getAccessibleComponent() {
  1869.             return this;
  1870.         }
  1871.  
  1872.  
  1873.         // AccessibleComponent methods
  1874.         //
  1875.         /**
  1876.          * Get the background color of this object.
  1877.          *
  1878.          * @return the background color, if supported, of the object;
  1879.          * otherwise, null
  1880.          */
  1881.         public Color getBackground() {
  1882.             return JComponent.this.getBackground();
  1883.         }
  1884.  
  1885.         // NOTE: IN THE NEXT MAJOR RELEASE, isOpaque WILL MIGRATE
  1886.         //       TO java.awt.Component -- ADJUST @SEE LINK BELOW.
  1887.         /**
  1888.          * Set the background color of this object.
  1889.          * (For transparency, see <code>isOpaque</code>.)
  1890.          *
  1891.          * @param c the new Color for the background
  1892.          * @see JComponent#isOpaque
  1893.          */
  1894.         public void setBackground(Color c) {
  1895.             JComponent.this.setBackground(c);
  1896.         }
  1897.  
  1898.         /**
  1899.          * Get the foreground color of this object.
  1900.          *
  1901.          * @return the foreground color, if supported, of the object;
  1902.          * otherwise, null
  1903.          */
  1904.         public Color getForeground() {
  1905.             return JComponent.this.getForeground();
  1906.         }
  1907.  
  1908.         /**
  1909.          * Set the foreground color of this object.
  1910.          *
  1911.          * @param c the new Color for the foreground
  1912.          */
  1913.         public void setForeground(Color c) {
  1914.             JComponent.this.setForeground(c);
  1915.         }
  1916.  
  1917.         /**
  1918.          * Get the Cursor of this object.
  1919.          *
  1920.          * @return the Cursor, if supported, of the object; otherwise, null
  1921.          */
  1922.         public Cursor getCursor() {
  1923.             return JComponent.this.getCursor();
  1924.         }
  1925.  
  1926.         /**
  1927.          * Set the Cursor of this object.
  1928.          *
  1929.          * @param c the new Cursor for the object
  1930.          */
  1931.         public void setCursor(Cursor cursor) {
  1932.             JComponent.this.setCursor(cursor);
  1933.         }
  1934.  
  1935.         /**
  1936.          * Get the Font of this object.
  1937.          *
  1938.          * @return the Font,if supported, for the object; otherwise, null
  1939.          */
  1940.         public Font getFont() {
  1941.             return JComponent.this.getFont();
  1942.         }
  1943.  
  1944.         /**
  1945.          * Set the Font of this object.
  1946.          *
  1947.          * @param f the new Font for the object
  1948.          */
  1949.         public void setFont(Font f) {
  1950.             JComponent.this.setFont(f);
  1951.         }
  1952.  
  1953.         /**
  1954.          * Get the FontMetrics of this object.
  1955.          *
  1956.          * @param f the Font
  1957.          * @return the FontMetrics, if supported, the object; otherwise, null
  1958.          * @see #getFont
  1959.          */
  1960.         public FontMetrics getFontMetrics(Font f) {
  1961.             return JComponent.this.getFontMetrics(f);
  1962.         }
  1963.  
  1964.         /**
  1965.          * Determine if the object is enabled.
  1966.          *
  1967.          * @return true if object is enabled; otherwise, false
  1968.          */
  1969.         public boolean isEnabled() {
  1970.             return JComponent.this.isEnabled();
  1971.         }
  1972.  
  1973.         /**
  1974.          * Set the enabled state of the object.
  1975.          *
  1976.          * @param b if true, enables this object; otherwise, disables it
  1977.          */
  1978.         public void setEnabled(boolean b) {
  1979.             boolean old = JComponent.this.isEnabled();
  1980.             JComponent.this.setEnabled(b);
  1981.             if (b != old) {
  1982.                 if (accessibleContext != null) {
  1983.                     if (b) {
  1984.                         accessibleContext.firePropertyChange(
  1985.                                 AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
  1986.                                 null, AccessibleState.ENABLED);
  1987.                     } else {
  1988.                         accessibleContext.firePropertyChange(
  1989.                                 AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
  1990.                                 AccessibleState.ENABLED, null);
  1991.                     }
  1992.                 }
  1993.             }
  1994.         }
  1995.  
  1996.         /**
  1997.          * Determine if the object is visible.  Note: this means that the
  1998.          * object intends to be visible; however, it may not in fact be
  1999.          * showing on the screen because one of the objects that this object
  2000.          * is contained by is not visible.  To determine if an object is
  2001.          * showing on the screen, use isShowing().
  2002.          *
  2003.          * @return true if object is visible; otherwise, false
  2004.          */
  2005.         public boolean isVisible() {
  2006.             return JComponent.this.isVisible();
  2007.         }
  2008.  
  2009.         /**
  2010.          * Set the visible state of the object.
  2011.          *
  2012.          * @param b if true, shows this object; otherwise, hides it
  2013.          */
  2014.         public void setVisible(boolean b) {
  2015.             boolean old = JComponent.this.isVisible();
  2016.             JComponent.this.setVisible(b);
  2017.             if (b != old) {
  2018.                 if (accessibleContext != null) {
  2019.                     if (b) {
  2020.                         accessibleContext.firePropertyChange(
  2021.                                 AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
  2022.                                 null, AccessibleState.VISIBLE);
  2023.                     } else {
  2024.                         accessibleContext.firePropertyChange(
  2025.                                 AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
  2026.                                 AccessibleState.VISIBLE, null);
  2027.                     }
  2028.                 }
  2029.             }
  2030.         }
  2031.  
  2032.         /**
  2033.          * Determine if the object is showing.  This is determined by checking
  2034.          * the visibility of the object and ancestors of the object.  Note:
  2035.          * this will return true even if the object is obscured by another
  2036.          * (for example, it happens to be underneath a menu that was pulled
  2037.          * down).
  2038.          *
  2039.          * @return true if object is showing; otherwise, false
  2040.          */
  2041.         public boolean isShowing() {
  2042.             return JComponent.this.isShowing();
  2043.         }
  2044.  
  2045.         /**
  2046.          * Checks whether the specified point is within this object's bounds,
  2047.          * where the point's x and y coordinates are defined to be relative to
  2048.          * the coordinate system of the object.
  2049.          *
  2050.          * @param p the Point relative to the coordinate system of the object
  2051.          * @return true if object contains Point; otherwise false
  2052.          */
  2053.         public boolean contains(Point p) {
  2054.             return JComponent.this.contains(p);
  2055.         }
  2056.  
  2057.         /**
  2058.          * Returns the location of the object on the screen.
  2059.          *
  2060.          * @return location of object on screen -- can be null if this object
  2061.          * is not on the screen
  2062.          */
  2063.         public Point getLocationOnScreen() {
  2064.             if (JComponent.this.isShowing()) {
  2065.                 return JComponent.this.getLocationOnScreen();
  2066.             } else {
  2067.                 return null;
  2068.             }
  2069.         }
  2070.  
  2071.         /**
  2072.          * Gets the location of the object relative to the parent in the form
  2073.          * of a point specifying the object's top-left corner in the screen's
  2074.          * coordinate space.
  2075.          *
  2076.          * @return An instance of Point representing the top-left corner of
  2077.          * the objects's bounds in the coordinate space of the screen; null if
  2078.          * this object or its parent are not on the screen
  2079.          */
  2080.         public Point getLocation() {
  2081.             return JComponent.this.getLocation();
  2082.         }
  2083.  
  2084.         /**
  2085.          * Sets the location of the object relative to the parent.
  2086.          */
  2087.         public void setLocation(Point p) {
  2088.             JComponent.this.setLocation(p);
  2089.         }
  2090.  
  2091.         /**
  2092.          * Gets the bounds of this object in the form of a Rectangle object.
  2093.          * The bounds specify this object's width, height, and location
  2094.          * relative to its parent.
  2095.          *
  2096.          * @return A rectangle indicating this component's bounds; null if
  2097.          * this object is not on the screen.
  2098.          */
  2099.         public Rectangle getBounds() {
  2100.             return JComponent.this.getBounds();
  2101.         }
  2102.  
  2103.         /**
  2104.          * Sets the bounds of this object in the form of a Rectangle object.
  2105.          * The bounds specify this object's width, height, and location
  2106.          * relative to its parent.
  2107.          *
  2108.          * @param A rectangle indicating this component's bounds
  2109.          */
  2110.         public void setBounds(Rectangle r) {
  2111.             JComponent.this.setBounds(r);
  2112.         }
  2113.  
  2114.         /**
  2115.          * Returns the size of this object in the form of a Dimension object.
  2116.          * The height field of the Dimension object contains this objects's
  2117.          * height, and the width field of the Dimension object contains this
  2118.          * object's width.
  2119.          *
  2120.          * @return A Dimension object that indicates the size of this
  2121.          *         component; null if this object is not on the screen
  2122.          */
  2123.         public Dimension getSize() {
  2124.             return JComponent.this.getSize();
  2125.         }
  2126.  
  2127.         /**
  2128.          * Resizes this object so that it has width width and height.
  2129.          *
  2130.          * @param d - The dimension specifying the new size of the object.
  2131.          */
  2132.         public void setSize(Dimension d) {
  2133.             JComponent.this.setSize(d);
  2134.         }
  2135.  
  2136.         /**
  2137.          * Returns the Accessible child, if one exists, contained at the local
  2138.          * coordinate Point.
  2139.          *
  2140.          * @param p The point defining the top-left corner of the Accessible,
  2141.          * given in the coordinate space of the object's parent.
  2142.          * @return the Accessible, if it exists, at the specified location;
  2143.          * else null
  2144.          */
  2145.         public Accessible getAccessibleAt(Point p) {
  2146.             return SwingUtilities.getAccessibleAt(JComponent.this, p);
  2147.         }
  2148.  
  2149.         /**
  2150.          * Returns whether this object can accept focus or not.
  2151.          *
  2152.          * @return true if object can accept focus; otherwise false
  2153.          */
  2154.         public boolean isFocusTraversable() {
  2155.             return JComponent.this.isFocusTraversable();
  2156.         }
  2157.  
  2158.         /**
  2159.          * Requests focus for this object.
  2160.          */
  2161.         public void requestFocus() {
  2162.             JComponent.this.requestFocus();
  2163.         }
  2164.  
  2165.         /**
  2166.          * Adds the specified focus listener to receive focus events from this
  2167.          * component.
  2168.          *
  2169.          * @param l the focus listener
  2170.          */
  2171.         public void addFocusListener(FocusListener l) {
  2172.             JComponent.this.addFocusListener(l);
  2173.         }
  2174.  
  2175.         /**
  2176.          * Removes the specified focus listener so it no longer receives focus
  2177.          * events from this component.
  2178.          *
  2179.          * @param l the focus listener
  2180.          */
  2181.         public void removeFocusListener(FocusListener l) {
  2182.             JComponent.this.removeFocusListener(l);
  2183.         }
  2184.  
  2185.     } // inner class AccessibleJComponent
  2186.  
  2187.  
  2188.     
  2189.     /**
  2190.      * @return a small Hashtable
  2191.      * @see #putClientProperty
  2192.      * @see #getClientProperty
  2193.      */
  2194.     private Dictionary getClientProperties() {
  2195.         if (clientProperties == null) {
  2196.             clientProperties = new Hashtable(2);
  2197.         }
  2198.         return clientProperties;
  2199.     }
  2200.  
  2201.  
  2202.     /**
  2203.      * Returns the value of the property with the specified key.  Only
  2204.      * properties added with <code>putClientProperty</code> will return
  2205.      * a non-null value.  
  2206.      * 
  2207.      * @return the value of this property or null
  2208.      * @see #putClientProperty
  2209.      */
  2210.     public final Object getClientProperty(Object key) {
  2211.         return getClientProperties().get(key);
  2212.     }
  2213.  
  2214.  
  2215.     /**
  2216.      * Add an arbitrary key/value "client property" to this component.
  2217.      * <p>
  2218.      * The <code>get/putClientProperty<code> methods provide access to 
  2219.      * a small per-instance hashtable. Callers can use get/putClientProperty
  2220.      * to annotate components that were created by another module, e.g. a 
  2221.      * layout manager might store per child constraints this way.  For example:
  2222.      * <pre>
  2223.      * componentA.putClientProperty("to the left of", componentB);
  2224.      * </pre>
  2225.      * <p>
  2226.      * If value is null this method will remove the property.
  2227.      * Changes to client properties are reported with PropertyChange
  2228.      * events.  The name of the property (for the sake of PropertyChange
  2229.      * events) is <code>key.toString()</code>.  
  2230.      * <p>
  2231.      * The clientProperty dictionary is not intended to support large 
  2232.      * scale extensions to JComponent nor should be it considered an 
  2233.      * alternative to subclassing when designing a new component.
  2234.      * 
  2235.      * @see #getClientProperty
  2236.      * @see #addPropertyChangeListener
  2237.      */
  2238.     public final void putClientProperty(Object key, Object value) {
  2239.         Object oldValue = getClientProperties().get(key);
  2240.  
  2241.         if (value != null) {
  2242.             getClientProperties().put(key, value);
  2243.         } else {
  2244.             getClientProperties().remove(key);
  2245.         }
  2246.  
  2247.         firePropertyChange(key.toString(), oldValue, value);
  2248.     }
  2249.  
  2250.  
  2251.     /* --- Transitional java.awt.Component Support ---
  2252.      *
  2253.      * The methods and fields in this section will migrate to
  2254.      * java.awt.Component in the next JDK release.
  2255.      *
  2256.      */
  2257.  
  2258.     private PropertyChangeSupport changeSupport;
  2259.  
  2260.  
  2261.     /**
  2262.      * Returns true if this component is a lightweight, i.e. if it doesn't
  2263.      * have a native window system peer.
  2264.      * <p>
  2265.      * This method will migrate to java.awt.Component in the next major JDK release
  2266.      *
  2267.      * @return true if this component is a lightweight
  2268.      */
  2269.     public static boolean isLightweightComponent(Component c) {
  2270.         return c.getPeer() instanceof java.awt.peer.LightweightPeer;
  2271.     }
  2272.  
  2273.  
  2274.     /**
  2275.      * Moves and resizes this component.
  2276.      *
  2277.      * @see java.awt.Component#setBounds
  2278.      */
  2279.     public void reshape(int x, int y, int w, int h) {
  2280.         if(isShowing()) {
  2281.             /* If there is an intersection between the new bounds and the old
  2282.              * one, refresh only the visible rects
  2283.              */
  2284.             if(!((_bounds.x + _bounds.width <= x) ||
  2285.                  (_bounds.y + _bounds.height <= y) ||
  2286.                  (_bounds.x >= (x + w)) ||
  2287.                  (_bounds.y >= (y + h)))) {
  2288.                 Rectangle[] rev = SwingUtilities.computeDifference(getBounds(),
  2289.                                                                    new Rectangle(x,y,w,h));
  2290.                 int i,c;
  2291.                 Container parent = getParent();
  2292.                 for(i=0,c=rev.length ; i < c ; i++) {
  2293.                     parent.repaint(rev[i].x,rev[i].y,rev[i].width,rev[i].height);
  2294.                     // System.out.println("Repaint " + rev[i]);
  2295.                 }
  2296.             } else {
  2297.                 getParent().repaint(_bounds.x,_bounds.y,_bounds.width,_bounds.height);
  2298.             }
  2299.         }
  2300.         _bounds.setBounds(x, y, w, h);
  2301.         super.reshape(x, y, w, h);
  2302.     }
  2303.  
  2304.     /**
  2305.      * Moves and resizes this component.
  2306.      *
  2307.      * @see java.awt.Component#setBounds
  2308.      */
  2309.     public void setBounds(Rectangle r) {
  2310.         _bounds.setBounds(r);
  2311.         super.setBounds(r);
  2312.     }
  2313.  
  2314.  
  2315.     /**
  2316.      * Store the bounds of this component into "return value" <b>rv</b> and
  2317.      * return <b>rv</b>.  If rv is null a new Rectangle is allocated.
  2318.      * This version of getBounds() is useful if the caller
  2319.      * wants to avoid allocating a new Rectangle object on the heap.
  2320.      *
  2321.      * @param rv the return value, modified to the components bounds
  2322.      * @return rv
  2323.      */
  2324.     public Rectangle getBounds(Rectangle rv) {
  2325.         if (rv == null) {
  2326.             return new Rectangle(getX(), getY(), getWidth(), getHeight());
  2327.         }
  2328.         else {
  2329.             rv.setBounds(getX(), getY(), getWidth(), getHeight());
  2330.             return rv;
  2331.         }
  2332.     }
  2333.  
  2334.  
  2335.     /**
  2336.      * Store the width/height of this component into "return value" <b>rv</b>
  2337.      * and return <b>rv</b>.   If rv is null a new Dimension object is
  2338.      * allocated.  This version of getSize() is useful if the
  2339.      * caller wants to avoid allocating a new Dimension object on the heap.
  2340.      *
  2341.      * @param rv the return value, modified to the components size
  2342.      * @return rv
  2343.      */
  2344.     public Dimension getSize(Dimension rv) {
  2345.         if (rv == null) {
  2346.             return new Dimension(getWidth(), getHeight());
  2347.         }
  2348.         else {
  2349.             rv.setSize(getWidth(), getHeight());
  2350.             return rv;
  2351.         }
  2352.     }
  2353.  
  2354.  
  2355.     /**
  2356.      * Store the x,y origin of this component into "return value" <b>rv</b>
  2357.      * and return <b>rv</b>.   If rv is null a new Point is allocated.
  2358.      * This version of getLocation() is useful if the
  2359.      * caller wants to avoid allocating a new Point object on the heap.
  2360.      *
  2361.      * @param rv the return value, modified to the components location
  2362.      * @return rv
  2363.      */
  2364.     public Point getLocation(Point rv) {
  2365.         if (rv == null) {
  2366.             return new Point(getX(), getY());
  2367.         }
  2368.         else {
  2369.             rv.setLocation(getX(), getY());
  2370.             return rv;
  2371.         }
  2372.     }
  2373.  
  2374.  
  2375.     /**
  2376.      * Return the current x coordinate of the components origin.
  2377.      * This method is preferable to writing component.getBounds().x,
  2378.      * or component.getLocation().x because it doesn't cause any
  2379.      * heap allocations.
  2380.      * <p>
  2381.      * This method will migrate to java.awt.Component in the next major JDK release
  2382.      *
  2383.      * @return the current x coordinate of the components origin.
  2384.      */
  2385.     public int getX() { return _bounds.x; }
  2386.  
  2387.  
  2388.     /**
  2389.      * Return the current y coordinate of the components origin.
  2390.      * This method is preferable to writing component.getBounds().y,
  2391.      * or component.getLocation().y because it doesn't cause any
  2392.      * heap allocations.
  2393.      * <p>
  2394.      * This method will migrate to java.awt.Component in the next major JDK release
  2395.      *
  2396.      * @return the current y coordinate of the components origin.
  2397.      */
  2398.     public int getY() { return _bounds.y; }
  2399.  
  2400.  
  2401.     /**
  2402.      * Return the current width of this component.
  2403.      * This method is preferable to writing component.getBounds().width,
  2404.      * or component.getSize().width because it doesn't cause any
  2405.      * heap allocations.
  2406.      * <p>
  2407.      * This method will migrate to java.awt.Component in the next major JDK release
  2408.      *
  2409.      * @return the current width of this component.
  2410.      */
  2411.     public int getWidth() { return _bounds.width; }
  2412.  
  2413.  
  2414.     /**
  2415.      * Return the current height of this component.
  2416.      * This method is preferable to writing component.getBounds().height,
  2417.      * or component.getSize().height because it doesn't cause any
  2418.      * heap allocations.
  2419.      * <p>
  2420.      * This method will migrate to java.awt.Component in the next major JDK release
  2421.      *
  2422.      * @return the current height of this component.
  2423.      */
  2424.     public int getHeight() { return _bounds.height; }
  2425.  
  2426.  
  2427.     /**
  2428.      * Returns true if this Component has the keyboard focus.
  2429.      * <p>
  2430.      * This method will migrate to java.awt.Component in the next major JDK release
  2431.      *
  2432.      * @return true if this Component has the keyboard focus.
  2433.      */
  2434.     public boolean hasFocus() {
  2435.         return getFlag(HAS_FOCUS);
  2436.     }
  2437.  
  2438.  
  2439.     /**
  2440.      * Returns true if this component is completely opaque.
  2441.      * <p>
  2442.      * An opaque component paints every pixel within its
  2443.      * rectangular region. A non-opaque component paints only some of
  2444.      * its pixels, allowing the pixels underneath it to "show through".
  2445.      * A component that does not fully paint its pixels therefore
  2446.      * provides a degree of transparency.
  2447.      * <p>
  2448.      * Subclasses that guarantee to always completely paint their contents should
  2449.      * override this method and return true.
  2450.      * <p>
  2451.      * This method will migrate to java.awt.Component in the next major JDK release
  2452.      *
  2453.      * @return true if this component is completely opaque.
  2454.      * @see #setOpaque
  2455.      */
  2456.     public boolean isOpaque() {
  2457.         return getFlag(IS_OPAQUE);
  2458.     }
  2459.  
  2460.  
  2461.     /**
  2462.      * If true the components background will be filled with the
  2463.      * background color. Otherwise, the background is transparent,
  2464.      * and whatever is underneath will show through.
  2465.      * <p>
  2466.      * The default value of this property is false.
  2467.      * <p>
  2468.      * This is a JavaBeans bound property.
  2469.      *
  2470.      * @see #isOpaque
  2471.      */
  2472.     public void setOpaque(boolean isOpaque) {
  2473.         boolean oldValue = getFlag(IS_OPAQUE);
  2474.         setFlag(IS_OPAQUE, isOpaque);
  2475.         firePropertyChange("opaque", oldValue, isOpaque);
  2476.     }
  2477.  
  2478.  
  2479.     /**
  2480.      * If the specified retangle is completely obscured by any of this
  2481.      * components opaque children then return true.  Only direct children
  2482.      * are considered, more distant descendants are ignored.  A JComponent
  2483.      * is opaque if JComponent.isOpaque() returns true, other lightweight
  2484.      * components are always considered transparent, and heavyweight components
  2485.      * are always considered opaque.
  2486.      *
  2487.      * @return true if the specified rectangle is obscured by an opaque child
  2488.      */
  2489.     boolean rectangleIsObscured(int x,int y,int width,int height)
  2490.     {
  2491.         Component children[] = getComponents();
  2492.  
  2493.  
  2494.         if(children == null) {
  2495.             return false;
  2496.         }
  2497.  
  2498.         for(int i = 0; i < children.length; i++) {
  2499.             Component child = children[i];
  2500.             Rectangle childBounds;
  2501.  
  2502.             if (child instanceof JComponent) {
  2503.                 childBounds = ((JComponent)child)._bounds;
  2504.             } else {
  2505.                 childBounds = child.getBounds();
  2506.             }
  2507.  
  2508.             if (x >= childBounds.x && (x + width) <= (childBounds.x + childBounds.width) &&
  2509.                 y >= childBounds.y && (y + height) <= (childBounds.y + childBounds.height)) {
  2510.  
  2511.                 if(child instanceof JComponent) {
  2512.                     return ((JComponent)child).isOpaque();
  2513.                 } else {
  2514.                     /** Sometimes an heavy weight can have a bound larger than it's peer size
  2515.                      *  so we should always draw under heavy weights
  2516.                      */
  2517.                     return false;
  2518.                 }
  2519.             }
  2520.         }
  2521.  
  2522.         return false;
  2523.     }
  2524.  
  2525.  
  2526.     /**
  2527.      * Returns the Component's "visible rect rectangle" -  the
  2528.      * intersection of the visible rectangles for this component
  2529.      * and all of its ancestors.  The return value is stored in
  2530.      * <code>visibleRect</code>
  2531.      *
  2532.      * @see #getVisibleRect
  2533.      */
  2534.     static final void computeVisibleRect(Component c, Rectangle visibleRect) {
  2535.         Container p = c.getParent();
  2536.         Rectangle bounds = c.getBounds();
  2537.  
  2538.         if (p == null || p instanceof Window || p instanceof Applet) {
  2539.             visibleRect.setBounds(0, 0, bounds.width, bounds.height);
  2540.         } else {
  2541.             computeVisibleRect(p, visibleRect);
  2542.             visibleRect.x -= bounds.x;
  2543.             visibleRect.y -= bounds.y;
  2544.             SwingUtilities.computeIntersection(0,0,bounds.width,bounds.height,visibleRect);
  2545.         }
  2546.     }
  2547.  
  2548.  
  2549.     /**
  2550.      * Returns the Component's "visible rect rectangle" -  the
  2551.      * intersection of the visible rectangles for this component
  2552.      * and all of its ancestors.  The return value is stored in
  2553.      * <code>visibleRect</code>
  2554.      *
  2555.      * @see #getVisibleRect
  2556.      */
  2557.     public void computeVisibleRect(Rectangle visibleRect) {
  2558.         computeVisibleRect(this, visibleRect);
  2559.     }
  2560.  
  2561.  
  2562.     /**
  2563.      * Returns the Component's "visible rectangle" -  the
  2564.      * intersection of this components visible rectangle:
  2565.      * <pre>
  2566.      * new Rectangle(0, 0, getWidth(), getHeight());
  2567.      * </pre>
  2568.      * and all of its ancestors visible Rectangles.
  2569.      *
  2570.      * @return the visible rectangle
  2571.      */
  2572.     public Rectangle getVisibleRect() {
  2573.         Rectangle visibleRect = new Rectangle();
  2574.  
  2575.         computeVisibleRect(visibleRect);
  2576.         return visibleRect;
  2577.     }
  2578.  
  2579.  
  2580.     /**
  2581.      * Support for reporting bound property changes.  If oldValue and
  2582.      * newValue are not equal and the PropertyChangeEvent listener list
  2583.      * isn't empty, then fire a PropertyChange event to each listener.
  2584.      * This method has an overloaded method for each primitive type.  For
  2585.      * example, here's how to write a bound property set method whose
  2586.      * value is an int:
  2587.      * <pre>
  2588.      * public void setFoo(int newValue) {
  2589.      *     int oldValue = foo;
  2590.      *     foo = newValue;
  2591.      *     firePropertyChange("foo", oldValue, newValue);
  2592.      * }
  2593.      * </pre>
  2594.      * <p>
  2595.      * This method will migrate to java.awt.Component in the next major JDK release
  2596.      *
  2597.      * @param propertyName  The programmatic name of the property that was changed.
  2598.      * @param oldValue  The old value of the property.
  2599.      * @param newValue  The new value of the property.
  2600.      * @see java.beans.PropertyChangeSupport
  2601.      */
  2602.     protected void firePropertyChange(String propertyName, Object oldValue, Object newValue) {
  2603.         if (changeSupport != null) {
  2604.             changeSupport.firePropertyChange(propertyName, oldValue, newValue);
  2605.         }
  2606.     }
  2607.  
  2608.     /*
  2609.      * PENDING(hmuller) in JDK1.2 the following firePropertyChange overloads
  2610.      * should additional check for a non-empty listener list with
  2611.      * changeSupport.hasListeners(propertyName) before calling firePropertyChange.
  2612.      */
  2613.  
  2614.     /**
  2615.      * @see #firePropertyChange(java.lang.String, java.lang.Object, java.lang.Object)
  2616.      */
  2617.     public void firePropertyChange(String propertyName, byte oldValue, byte newValue) {
  2618.         if ((changeSupport != null) && (oldValue != newValue)) {
  2619.             changeSupport.firePropertyChange(propertyName, new Byte(oldValue), new Byte(newValue));
  2620.         }
  2621.     }
  2622.  
  2623.     /**
  2624.      * @see #firePropertyChange(java.lang.String, java.lang.Object, java.lang.Object)
  2625.      */
  2626.      public void firePropertyChange(String propertyName, char oldValue, char newValue) {
  2627.          if ((changeSupport != null) && (oldValue != newValue)) {
  2628.              changeSupport.firePropertyChange(propertyName, new Character(oldValue), new Character(newValue));
  2629.          }
  2630.     }
  2631.  
  2632.     /**
  2633.      * @see #firePropertyChange(java.lang.String, java.lang.Object, java.lang.Object)
  2634.      */
  2635.     public void firePropertyChange(String propertyName, short oldValue, short newValue) {
  2636.         if ((changeSupport != null) && (oldValue != newValue)) {
  2637.             changeSupport.firePropertyChange(propertyName, new Short(oldValue), new Short(newValue));
  2638.         }
  2639.     }
  2640.  
  2641.     /**
  2642.      * @see #firePropertyChange(java.lang.String, java.lang.Object, java.lang.Object)
  2643.      */
  2644.     public void firePropertyChange(String propertyName, int oldValue, int newValue) {
  2645.         if ((changeSupport != null) && (oldValue != newValue)) {
  2646.             changeSupport.firePropertyChange(propertyName, new Integer(oldValue), new Integer(newValue));
  2647.         }
  2648.     }
  2649.  
  2650.     /**
  2651.      * @see #firePropertyChange(java.lang.String, java.lang.Object, java.lang.Object)
  2652.      */
  2653.     public void firePropertyChange(String propertyName, long oldValue, long newValue) {
  2654.         if ((changeSupport != null) && (oldValue != newValue)) {
  2655.             changeSupport.firePropertyChange(propertyName, new Long(oldValue), new Long(newValue));
  2656.         }
  2657.     }
  2658.  
  2659.     /**
  2660.      * @see #firePropertyChange(java.lang.String, java.lang.Object, java.lang.Object)
  2661.      */
  2662.     public void firePropertyChange(String propertyName, float oldValue, float newValue) {
  2663.         if ((changeSupport != null) && (oldValue != newValue)) {
  2664.             changeSupport.firePropertyChange(propertyName, new Float(oldValue), new Float(newValue));
  2665.         }
  2666.     }
  2667.  
  2668.     /**
  2669.      * @see #firePropertyChange(java.lang.String, java.lang.Object, java.lang.Object)
  2670.      */
  2671.     public void firePropertyChange(String propertyName, double oldValue, double newValue) {
  2672.         if ((changeSupport != null) && (oldValue != newValue)) {
  2673.             changeSupport.firePropertyChange(propertyName, new Double(oldValue), new Double(newValue));
  2674.         }
  2675.     }
  2676.  
  2677.     /**
  2678.      * @see #firePropertyChange(java.lang.String, java.lang.Object, java.lang.Object)
  2679.      */
  2680.     public void firePropertyChange(String propertyName, boolean oldValue, boolean newValue) {
  2681.         if ((changeSupport != null) && (oldValue != newValue)) {
  2682.             changeSupport.firePropertyChange(propertyName, new Boolean(oldValue), new Boolean(newValue));
  2683.         }
  2684.     }
  2685.  
  2686.  
  2687.     /**
  2688.      * Add a PropertyChangeListener to the listener list.
  2689.      * The listener is registered for all properties.
  2690.      * <p>
  2691.      * A PropertyChangeEvent will get fired in response to setting
  2692.      * a bound property, e.g. setFont, setBackground, or setForeground.
  2693.      * Note that if the current component is inheriting its foreground,
  2694.      * background, or font from its container, then no event will be
  2695.      * fired in response to a change in the inherited property.
  2696.      * <p>
  2697.      * This method will migrate to java.awt.Component in the next major JDK release
  2698.      *
  2699.      * @param listener  The PropertyChangeListener to be added
  2700.      */
  2701.     public synchronized void addPropertyChangeListener(PropertyChangeListener listener) {
  2702.         if (changeSupport == null) {
  2703.             changeSupport = new java.beans.PropertyChangeSupport(this);
  2704.         }
  2705.         changeSupport.addPropertyChangeListener(listener);
  2706.     }
  2707.  
  2708.  
  2709.     /**
  2710.      * Remove a PropertyChangeListener from the listener list.
  2711.      * This removes a PropertyChangeListener that was registered
  2712.      * for all properties.
  2713.      * <p>
  2714.      * This method will migrate to java.awt.Component in the next major JDK release
  2715.      *
  2716.      * @param listener  The PropertyChangeListener to be removed
  2717.      */
  2718.     public synchronized void removePropertyChangeListener(PropertyChangeListener listener) {
  2719.         if (changeSupport != null) {
  2720.             changeSupport.removePropertyChangeListener(listener);
  2721.         }
  2722.     }
  2723.  
  2724.  
  2725.     /**
  2726.      * Support for reporting constrained property changes.  This method can be called
  2727.      * when a constrained property has changed and it will send the appropriate
  2728.      * PropertyChangeEvent to any registered VetoableChangeListeners.
  2729.      * <p>
  2730.      * This method will migrate to java.awt.Component in the next major JDK release
  2731.      *
  2732.      * @exception PropertyVetoException when the attempt to set the property is vetoed
  2733.      *            by the receiver.
  2734.      */
  2735.     protected void fireVetoableChange(String propertyName, Object oldValue, Object newValue)
  2736.         throws java.beans.PropertyVetoException
  2737.     {
  2738.         if (vetoableChangeSupport == null) {
  2739.             return;
  2740.         }
  2741.         vetoableChangeSupport.fireVetoableChange(propertyName, oldValue, newValue);
  2742.     }
  2743.  
  2744.  
  2745.     /**
  2746.      * Add a VetoableChangeListener to the listener list.
  2747.      * The listener is registered for all properties.
  2748.      * <p>
  2749.      * This method will migrate to java.awt.Component in the next major JDK release
  2750.      *
  2751.      * @param listener  The VetoableChangeListener to be added
  2752.      */
  2753.     public synchronized void addVetoableChangeListener(VetoableChangeListener listener) {
  2754.         if (vetoableChangeSupport == null) {
  2755.             vetoableChangeSupport = new java.beans.VetoableChangeSupport(this);
  2756.         }
  2757.         vetoableChangeSupport.addVetoableChangeListener(listener);
  2758.     }
  2759.  
  2760.  
  2761.     /**
  2762.      * Remove a VetoableChangeListener from the listener list.
  2763.      * This removes a VetoableChangeListener that was registered
  2764.      * for all properties.
  2765.      * <p>
  2766.      * This method will migrate to java.awt.Component in the next major JDK release
  2767.      *
  2768.      * @param listener  The VetoableChangeListener to be removed
  2769.      */
  2770.     public synchronized void removeVetoableChangeListener(VetoableChangeListener listener) {
  2771.         if (vetoableChangeSupport == null) {
  2772.             return;
  2773.         }
  2774.         vetoableChangeSupport.removeVetoableChangeListener(listener);
  2775.     }
  2776.  
  2777.  
  2778.     /**
  2779.      * Returns the top-level ancestor of this component (either the
  2780.      * containing Window or Applet), or null if this component has not
  2781.      * been added to any container.
  2782.      *
  2783.      * @return the top-level Container which this component is in.
  2784.      */
  2785.     public Container getTopLevelAncestor() {
  2786.         for(Container p = this; p != null; p = p.getParent()) {
  2787.             if(p instanceof Window || p instanceof Applet) {
  2788.                 return p;
  2789.             }
  2790.         }
  2791.         return null;
  2792.     }
  2793.  
  2794.  
  2795.     /**
  2796.      * Registers <i>listener</i> so that it will receive AncestorEvents
  2797.      * when it or any of its ancestors move or are made visible / invisible.
  2798.      * Events are also sent when the component or its ancestors are added
  2799.      * or removed from the Component hierarchy
  2800.      * <p>
  2801.      * This method will migrate to java.awt.Component in the next major JDK release
  2802.      *
  2803.      * @see AncestorEvent
  2804.      */
  2805.     public void addAncestorListener(AncestorListener listener) {
  2806.         if (ancestorNotifier == null) {
  2807.             ancestorNotifier = new AncestorNotifier(this);
  2808.         }
  2809.         ancestorNotifier.addAncestorListener(listener);
  2810.     }
  2811.  
  2812.     /**
  2813.      * Unregisters <i>listener</i> so that it will no longer receive
  2814.      * AncestorEvents
  2815.      * <p>
  2816.      * This method will migrate to java.awt.Component in the next major JDK release
  2817.      *
  2818.      * @see #addAncestorListener
  2819.      */
  2820.     public void removeAncestorListener(AncestorListener listener) {
  2821.         if (ancestorNotifier == null) {
  2822.             return;
  2823.         }
  2824.         ancestorNotifier.removeAncestorListener(listener);
  2825.         if (ancestorNotifier.listenerList.getListenerList().length == 0) {
  2826.             ancestorNotifier.removeAllListeners();
  2827.             ancestorNotifier = null;
  2828.         }
  2829.     }
  2830.  
  2831.  
  2832.     /**
  2833.      * Notification to this component that it now has a parent component.
  2834.      * When this method is invoked, the chain of parent components is
  2835.      * set up with KeyboardAction event listeners.
  2836.      *
  2837.      * @see #registerKeyboardAction
  2838.      */
  2839.     public void addNotify() {
  2840.         super.addNotify();
  2841.         firePropertyChange("ancestor", null, getParent());
  2842.     }
  2843.  
  2844.  
  2845.     /**
  2846.      * Notification to this component that it no longer has a parent component.
  2847.      * When this method is invoked, any KeyboardActions set up in the
  2848.      * the chain of parent components are removed.
  2849.      *
  2850.      * @see #registerKeyboardAction
  2851.      */
  2852.     public void removeNotify() {
  2853.         super.removeNotify();
  2854.         // This isn't strictly correct.  The event shouldn't be
  2855.         // fired until *after* the parent is set to null.  But
  2856.         // we only get notified before that happens
  2857.         firePropertyChange("ancestor", getParent(), null);
  2858.     }
  2859.  
  2860.  
  2861.     /**
  2862.      * Adds the specified region to the dirty region list if the component
  2863.      * is showing.  The component will be repainted after all of the
  2864.      * currently pending events have been dispatched.
  2865.      *
  2866.      * @see java.awt.Component#isShowing
  2867.      * @see RepaintManager#addDirtyRegion
  2868.      */
  2869.     public void repaint(long tm, int x, int y, int width, int height) {
  2870.         RepaintManager.currentManager(this).addDirtyRegion(this, x, y, width, height);
  2871.     }
  2872.  
  2873.  
  2874.     /**
  2875.      * Adds the specified region to the dirty region list if the component
  2876.      * is showing.  The component will be repainted after all of the
  2877.      * currently pending events have been dispatched.
  2878.      *
  2879.      * @see java.awt.Component#isShowing
  2880.      * @see RepaintManager#addDirtyRegion
  2881.      */
  2882.     public void repaint(Rectangle r) {
  2883.         repaint(0,r.x,r.y,r.width,r.height);
  2884.     }
  2885.  
  2886.  
  2887.     /**
  2888.      * Support for deferred automatic layout.
  2889.      * <p>
  2890.      * Calls invalidate() and then adds this components validateRoot
  2891.      * to a list of components that need to be validated.  Validation
  2892.      * will occur after all currently pending events have been dispatched.
  2893.      * By default only JScrollPane.isValidateRoot() returns true.  In other
  2894.      * words after this method is called,  the first JScrollPane that
  2895.      * contains this component (if any) will be validated.
  2896.      *
  2897.      * @see java.awt.Component#invalidate
  2898.      * @see java.awt.Container#validate
  2899.      * @see #isValidateRoot
  2900.      * @see RepaintManager#addInvalidComponent
  2901.      */
  2902.     public void revalidate() {
  2903.         if (SwingUtilities.isEventDispatchThread()) {
  2904.             invalidate();
  2905.             RepaintManager.currentManager(this).addInvalidComponent(this);
  2906.         }
  2907.         else {
  2908.             Runnable callRevalidate = new Runnable() {
  2909.                 public void run() {
  2910.                     revalidate();
  2911.                 }
  2912.             };
  2913.             SwingUtilities.invokeLater(callRevalidate);
  2914.         }
  2915.     }
  2916.  
  2917.  
  2918.     /**
  2919.      * If this method returns true, revalidate() calls by descendants of
  2920.      * this component will cause the entire tree beginning with this root
  2921.      * to be validated.  Returns false by default.  JScrollPane overrides
  2922.      * this method and returns true.
  2923.      *
  2924.      * @return false
  2925.      * @see #revalidate
  2926.      * @see java.awt.Component#invalidate
  2927.      * @see java.awt.Container#validate
  2928.      */
  2929.     public boolean isValidateRoot() {
  2930.         return false;
  2931.     }
  2932.  
  2933.  
  2934.     /**
  2935.      * Returns true if this component tiles its children, i.e. if
  2936.      * it can guarantee that the children will not overlap.  The
  2937.      * repainting system is substantially more efficient in this
  2938.      * common case.  JComponent subclasses that can't make this
  2939.      * guarantee, e.g. JLayeredPane, should override this method
  2940.      * to return false.
  2941.      *
  2942.      * @return true if this components children don't overlap
  2943.      */
  2944.     public boolean isOptimizedDrawingEnabled() {
  2945.         return true;
  2946.     }
  2947.  
  2948.  
  2949.     /**
  2950.      * Paint the specified region in this component and all of its
  2951.      * descendants that overlap the region, immediately.
  2952.      * <p>
  2953.      * It's rarely neccessary to call this method.  In most cases it's
  2954.      * more efficient to call repaint which defers the actual painting
  2955.      * and can collapse redundant requests into a single paint call.
  2956.      * This method is useful if one needs to update the display while
  2957.      * the current event is being dispatched.
  2958.      *
  2959.      * @see #repaint
  2960.      */
  2961.     public void paintImmediately(int x,int y,int w, int h) {
  2962.         Component c = this;
  2963.         Component parent;
  2964.         Rectangle bounds;
  2965.  
  2966.         if(!isShowing()) {
  2967.             return;
  2968.         }
  2969.         while(!((JComponent)c).isOpaque()) {
  2970.             parent = c.getParent();
  2971.             if(parent != null) {
  2972.                 if(c instanceof JComponent) {
  2973.                     bounds = ((JComponent)c)._bounds;
  2974.                 } else {
  2975.                     bounds = c.getBounds();
  2976.                 }
  2977.                 x += bounds.x;
  2978.                 y += bounds.y;
  2979.                 c = parent;
  2980.             } else {
  2981.                 break;
  2982.             }
  2983.  
  2984.             if(!(c instanceof JComponent)) {
  2985.                 break;
  2986.             }
  2987.         }
  2988.         if(c instanceof JComponent) {
  2989.             ((JComponent)c)._paintImmediately(x,y,w,h);
  2990.         } else {
  2991.             c.repaint(x,y,w,h);
  2992.         }
  2993.     }
  2994.  
  2995.     /**
  2996.      * Paint the specified region now.
  2997.      * <p>
  2998.      * This method will migrate to java.awt.Component in the next major JDK release
  2999.      */
  3000.     public void paintImmediately(Rectangle r) {
  3001.         paintImmediately(r.x,r.y,r.width,r.height);
  3002.     }
  3003.  
  3004.  
  3005.     void _paintImmediately(int x, int y, int w, int h) {
  3006.         Graphics g;
  3007.         Container c;
  3008.         Rectangle clip = new Rectangle(x,y,w,h);
  3009.         Rectangle b;
  3010.         if(tmpRect == null) {
  3011.             tmpRect = new Rectangle();
  3012.         }
  3013.         tmpRect.x=tmpRect.y=0;
  3014.         int offsetX=0,offsetY=0;
  3015.         int bufferOffsetX=0,bufferOffsetY=0;
  3016.         boolean hasBuffer = false;
  3017.         JComponent bufferedComponent = null;
  3018.         JComponent paintingComponent = this;
  3019.         RepaintManager repaintManager = RepaintManager.currentManager(this);
  3020.  
  3021.         for (c = this;
  3022.              c != null && !(c instanceof Window) && !(c instanceof Applet);
  3023.              c = c.getParent()) {
  3024.              if ((c instanceof JComponent) && !(((JComponent)c).isOptimizedDrawingEnabled())) {
  3025.                 paintingComponent = (JComponent)c;
  3026.                 offsetX = offsetY = 0;
  3027.                 hasBuffer = false; /** Get rid of any buffer since we draw from here and
  3028.                                     *  we might draw something larger
  3029.                                     */
  3030.             }
  3031.  
  3032.             if(repaintManager.isDoubleBufferingEnabled() &&
  3033.                (c instanceof JComponent) && ((JComponent)c).isDoubleBuffered()) {
  3034.                 hasBuffer = true;
  3035.                 bufferedComponent = (JComponent)c;
  3036.                 bufferOffsetX = offsetX;
  3037.                 bufferOffsetY = offsetY;
  3038.             }
  3039.             if(c instanceof JComponent) {
  3040.                 b = ((JComponent)c)._bounds;
  3041.             } else {
  3042.                 b = c.getBounds();
  3043.             }
  3044.             tmpRect.width = b.width;
  3045.             tmpRect.height = b.height;
  3046.             SwingUtilities.computeIntersection(tmpRect.x,tmpRect.y,tmpRect.width,tmpRect.height,clip);
  3047.             clip.x += b.x;
  3048.             clip.y += b.y;
  3049.             offsetX += b.x;
  3050.             offsetY += b.y;
  3051.         }
  3052.  
  3053.         if(c == null || c.getPeer() == null) {
  3054.             return;
  3055.         }
  3056.  
  3057.         clip.x -= offsetX;
  3058.         clip.y -= offsetY;
  3059.  
  3060.         try {
  3061.             g = SwingGraphics.createSwingGraphics(paintingComponent.getGraphics());
  3062.         } catch(NullPointerException e) {
  3063.             g = null;
  3064.             e.printStackTrace();
  3065.         }
  3066.  
  3067.         if(g == null) {
  3068.             System.err.println("In paintImmediately null graphics");
  3069.             return;
  3070.         }
  3071.  
  3072.         if(hasBuffer) {
  3073.             Image offscreen = repaintManager.getOffscreenBuffer(bufferedComponent,clip.width,clip.height);
  3074.             paintWithBuffer(paintingComponent,g,clip,offscreen);
  3075.             g.dispose();
  3076.         } else {
  3077.             g.setClip(clip.x,clip.y,clip.width,clip.height);
  3078.             try {
  3079.                 paintingComponent.paint(g);
  3080.             } finally {
  3081.                 g.dispose();
  3082.             }
  3083.         }
  3084.     }
  3085.  
  3086.     private void paintWithBuffer(JComponent paintingComponent,Graphics g,Rectangle clip,Image offscreen) {
  3087.         Graphics og = SwingGraphics.createSwingGraphics(offscreen.getGraphics());
  3088.         int bw = offscreen.getWidth(null);
  3089.         int bh = offscreen.getHeight(null);
  3090.         int x,y,maxx,maxy;
  3091.  
  3092.         if(bw > clip.width) {
  3093.             bw = clip.width;
  3094.         }
  3095.         if(bh > clip.height) {
  3096.             bh = clip.height;
  3097.         }
  3098.  
  3099.         try {
  3100.             paintingComponent.setFlag(ANCESTOR_USING_BUFFER,true);
  3101.             paintingComponent.setFlag(IS_PAINTING_TILE,true);
  3102.             for(x = clip.x, maxx = clip.x+clip.width;
  3103.                 x < maxx ;  x += bw ) {
  3104.                 for(y=clip.y, maxy = clip.y + clip.height;
  3105.                     y < maxy ; y += bh) {
  3106.                     if((y+bh) >= maxy && (x+bw) >= maxx) {
  3107.                         paintingComponent.setFlag(IS_PAINTING_TILE,false);
  3108.                     }
  3109.                     og.translate(-x,-y);
  3110.                     og.setClip(x,y,bw,bh);
  3111.                     paintingComponent.paint(og);
  3112.                     g.setClip(x,y,bw,bh);
  3113.                     g.drawImage(offscreen,x,y,paintingComponent);
  3114.                     og.translate(x,y);
  3115.                 }
  3116.             }
  3117.         } finally {
  3118.             paintingComponent.setFlag(ANCESTOR_USING_BUFFER,false);
  3119.             paintingComponent.setFlag(IS_PAINTING_TILE,false);
  3120.             og.dispose();
  3121.         }
  3122.     }
  3123.  
  3124.  
  3125.     private void setFlag(int aFlag, boolean aValue) {
  3126.         if(aValue) {
  3127.             flags |= (1 << aFlag);
  3128.         } else {
  3129.             flags &= ~(1 << aFlag);
  3130.         }
  3131.     }
  3132.  
  3133.     private boolean getFlag(int aFlag) {
  3134.         int mask = (1 << aFlag);
  3135.         return ((flags & mask) == mask);
  3136.     }
  3137.  
  3138.  
  3139.     /** Buffering **/
  3140.  
  3141.     /** Set whether the receiving component should use a buffer to paint.
  3142.      *  If set to true, all the drawing from this component will be done
  3143.      *  in an offscreen painting buffer. The offscreen painting buffer will
  3144.      *  the be copied onto the screen.
  3145.      *  Swing's painting system always use a maximum of one double buffer.
  3146.      *  If a Component is buffered and one of its ancestor is also buffered,
  3147.      *  the ancestor buffer will be used.
  3148.      */
  3149.     public void setDoubleBuffered(boolean aFlag) {
  3150.         setFlag(IS_DOUBLE_BUFFERED,aFlag);
  3151.     }
  3152.  
  3153.     /** Return whether the receiving component should use a buffer to paint. **/
  3154.     public boolean isDoubleBuffered() {
  3155.         return getFlag(IS_DOUBLE_BUFFERED);
  3156.     }
  3157.  
  3158.     /**
  3159.      * Returns the JRootPane ancestor for a component
  3160.      *
  3161.      * @return the JRootPane that contains this component,
  3162.      *         or null if no JRootPane is found
  3163.      */
  3164.     public JRootPane getRootPane() {
  3165.         return SwingUtilities.getRootPane(this);
  3166.     }
  3167.  
  3168.  
  3169.     /** Serialization **/
  3170.  
  3171.     /*
  3172.     private void writeObject(ObjectOutputStream s) throws IOException {
  3173.         s.defaultWriteObject();
  3174.     }
  3175.  
  3176.  
  3177.     private void readObject(ObjectInputStream s)
  3178.         throws IOException, ClassNotFoundException
  3179.     {
  3180.         s.defaultReadObject();
  3181.         updateUI();
  3182.     }
  3183.     */
  3184. }
  3185.